Suppose the following class hierarchy : (If you don't know what virtual inheritance means read this).
class A { };
class B1 : public virtual A { };
class B2 : public virtual A { };
class C : public B1, public B2 { };
Now suppose A has a non-trivial constructor, for instance like this:
class A {
public:
A(int i) { /* ... */ }
};
Because B1 and B2 may disagree on how A must be initialized, A must be initialized from C. This might look like this:
class C {
C() : A(42) { }
};
In my special case, B1 and B2 are meant to be used within the diamond only. But the compiler does not know this. It could be that another compilation unit defines a class which inherits from B1 without creating a diamond. In this case B1 must initialize A. So B1 needs to call A's constructor. This looks like this:
class A {
public:
A(int i) { /* ... */ }
};
class B1 : public virtual A {
public:
B1() : A(0) { }
};
class B2 : public virtual A {
public:
B2() : A(0) { }
};
class C : public B1, public B2 {
public:
C() : A(42) { }
};
Without going into much detail, in the case I encountered there is no meaningful value B1 or B2 could initialize A with. Not only that I have to define an initializer which is never called, I must find some I-don't-really-mean-it value to not initialize A with. What a mess.
Alternatively you could define a default constructor for A which is never called. Perhaps like this:
class A {
A(int i) { /* ... */ }
A() { assert(false); }
};
which is not really better.
Well, what should I say, this is C++...
No comments:
Post a Comment