C++ 只有1个虚拟继承的菱形问题

C++ 只有1个虚拟继承的菱形问题,c++,virtual-inheritance,diamond-problem,C++,Virtual Inheritance,Diamond Problem,这还能解决钻石问题吗 class A {}; class B : virtual A {}; class C : A {}; class D : B, C {}; 编辑:如果不是,那是什么?和这个一样吗 class A {}; class B : A {}; class C : A {}; class D : B, C {}; class A {}; class B : A {}; class C : A {}; class D : B, C {}; 还是别的什么?不,不

这还能解决钻石问题吗

class A
{};

class B : virtual A
{};

class C : A
{};

class D : B, C
{};
编辑:如果不是,那是什么?和这个一样吗

class A
{};

class B : A
{};

class C : A
{};

class D : B, C
{};
class A
{};

class B : A
{};

class C : A
{};

class D : B, C
{};

还是别的什么?不,不会。
B
C
都必须从
A
虚拟继承。

菱形问题和对公共基础成员的模糊调用可以通过以下图形等价物来最好地描述,这也提供了对内存模型的深入了解

例1 由于继承只是将两个对象的实现一个接一个地放在一起,所以基类A的所有方法都会在派生类B和C中重复,这两个类具有与

                          A              A
                          |              |
                          |              |
                           B             C
                             \         /
                                \    /
                                  D
例2 使用virtual关键字,编译器为派生类B生成一个vtable,其中B的vtable中有一个vptr(虚拟指针),该vtable存储基类a的偏移量。对于C,它仍然复制基类a的所有方法。因此,类D,via基类B指通过vptr的基类A的成员,其中类C指的是作为副本的基类A的成员。因此,钻石问题和模糊性仍然存在

                               A         A
                             /           |
                           /             |
                           B             C
                             \         /
                                \    /
                                  D
例3 现在,当派生类B和C都虚拟继承A时,编译器为B和C创建一个Vtable,并在其每个Vtable中创建一个vptr,以引用基类A的偏移量。这最终解决了菱形问题,因为只有一个副本通过B或C可见

                                  A                                          
                               /     \
                             /         \                                
                           B             C
                             \         /
                                \    /
                                  D

如果从A类到B的标记为虚而非类为C,则C++将创建单个虚拟A(D继承B,B继承A)和非虚A(D继承C,C继承A)。因此,如果您想访问a的成员,那么下面的代码将无法解决菱形问题

class A
{};

class B : virtual A
{};

class C : A
{};

class D : B, C
{};
和这个一样吗

class A
{};

class B : A
{};

class C : A
{};

class D : B, C
{};
class A
{};

class B : A
{};

class C : A
{};

class D : B, C
{};
上面的代码将为A的每个继承路径创建两个非虚拟A(D继承B,B继承A;D继承C,C继承A)

因此,两种情况的结果是相同的:钻石问题无法解决


<>最后,您应该为“继承”从“A”到“B”,“A”到“C.”,在这种情况下,C++只创建一个对象。p> 请参见对我的问题的编辑。你也能提到这个吗?
class A
{};

class B : A
{};

class C : A
{};

class D : B, C
{};