问题
Does this still solve the diamond problem?
class A
{};
class B : virtual A
{};
class C : A
{};
class D : B, C
{};
Edit: If not, what is it then? Is it the same as this?
class A
{};
class B : A
{};
class C : A
{};
class D : B, C
{};
Or is it something even else?
回答1:
Diamond problem and ambiguous call to common base members can be best described through the following pictorial equivalent which also give an insight of the memory model
Example 1
class A
{void foo(){};};
class B :public A
{};
class C :public A
{};
class D :public B,public C
{};
Since Inheritance simply puts the implementation of two objects one after another, all methods of Base class A gets duplicated in derived class B and C, which has an equivalent pictorial representation as
A A
| |
| |
B C
\ /
\ /
D
Example 2
class A
{};
class B :public virtual A
{};
class C :public A
{};
class D :public B,public C
{};
With the virtual keyword, compiler generates a vtable for Derived class B with a vptr (virtual pointer) in the vtable of B which stores an Offset of the Base class A. For C, it still copies all method of base class A. So class D, via Base class B refers the members of base class A via a vptr where are Class C refers the members of base class A as a duplicate copy. So the diamond problem and ambiguity still persist.
A A
/ |
/ |
B C
\ /
\ /
D
Example 3
class A
{};
class B :public virtual A
{};
class C :public virtual A
{};
class D :public B,public C
{};
Now when both the derived classes B and C inherits A virtually, Compiler creates a Vtable for both B and C and creates a vptr in each of its vtable to refer the offset of the Base Class A. This finally solves the Diamond Problem as there is only one copy visible via B or C
A
/ \
/ \
B C
\ /
\ /
D
回答2:
No, it will not. Both B
and C
have to inherit from A
virtually.
回答3:
If the inheritance from the A class to B marked virtual but not A class to C, then C++ will create a single virtual A (D inherits B, B inherits A) and a nonvirtual A (D inherits C, C inherits A). Therefore, your following code will not solve the diamond problem if you want to access a member of A.
class A
{};
class B : virtual A
{};
class C : A
{};
class D : B, C
{};
Is it the same as this?
class A
{};
class B : A
{};
class C : A
{};
class D : B, C
{};
The above code will create two nonvirtual A for each inheritance path to A (D inherits B, B inherits A; D inherits C, C inherits A).
Therefore, the result for both case is the same: diamond problem cannot be solve.
Finally, you should make "virtual" for both inheritance from A to B and A to C. In this case, C++ will only create one A object.
来源:https://stackoverflow.com/questions/26534945/diamond-problem-with-only-1-virtual-inheritance