Diamond problem with only 1 virtual inheritance

淺唱寂寞╮ 提交于 2019-12-12 15:04:00

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!