具有混合虚拟和非虚拟基础的C++ 11类格?

And*_*zos 7 c++ c++11

在C++ 11(N3485)10.1.4 [class.mi]中它说:

对于最派生类的类点阵中非虚拟基类的每个不同出现,最派生的对象应包含该类型的对应的不同基类子对象.

对于指定为virtual的每个不同的基类,最派生的类应包含该类型的单个基类对象.

考虑以下C++ 11代码:

struct B {};

struct BV : virtual B {};
struct BN : B {};

struct C1 : BV, BN {};
struct C2 : BV, BN {};

struct D : C1, C2 {};
Run Code Online (Sandbox Code Playgroud)

首先,为清楚起见,D的类格子有多少个顶点?

其次,B类有多少个不同的子对象,标准要求D类型的派生对象有多少?

更新:

以下哪一类是格子?

(1)

    B     B     B    B
    ^     ^     ^    ^
    |     |     |    |
    BV    BN    BV   BN
    ^     ^     ^    ^
    |     |     |    |
     \   /       \  /
       C1         C2
         \        /
          \      /
           -  D -
Run Code Online (Sandbox Code Playgroud)

(2)

    B<---------
    ^          \
    |           |
    |     B     |    B
    |     ^     |    ^
    |     |     |    |
    BV    BN    BV   BN
    ^     ^     ^    ^
    |     |     |    |
     \   /       \  /
       C1         C2
         \        /
          \      /
           -  D -
Run Code Online (Sandbox Code Playgroud)

(3)

       B   
      /  \     
     /    \ 
    BV    BN
    | \  / |
    |  \/  |
    |  / \ |
    | /   \|
    C1     C2
     \    /
      \  /
       D
Run Code Online (Sandbox Code Playgroud)

如果意图是(1)那么是不是不可能有任何不是树的DAG?(即钻石是不可能的)如果是这样的话,将它称为类树是不是更好?

如果是(2)说"对于类格中基类的每次出现都有一个相应的基类子对象"是不够的.也就是说,如果格子的构造已经依赖于虚拟和非虚基类关系来选择边和顶点?

如果是(3)那么标准中的语言不正确,因为类格子中只能出现一个类?

How*_*ant 3

\n

以下哪一个是类格?

\n
\n\n

2

\n\n

示范:

\n\n
#include <iostream>\n\nstruct B {};\n\nstruct BV : virtual B {};\nstruct BN : B {};\n\nstruct C1 : BV, BN {};\nstruct C2 : BV, BN {};\n\nstruct D : C1, C2 {};\n\nint\nmain()\n{\n    D d;\n    C1* c1 = static_cast<C1*>(&d);\n    BV* bv1 = static_cast<BV*>(c1);\n    BN* bn1 = static_cast<BN*>(c1);\n    B* b1 = static_cast<B*>(bv1);\n    B* b2 = static_cast<B*>(bn1);\n    C2* c2 = static_cast<C2*>(&d);\n    BV* bv2 = static_cast<BV*>(c2);\n    BN* bn2 = static_cast<BN*>(c2);\n    B* b3 = static_cast<B*>(bv2);\n    B* b4 = static_cast<B*>(bn2);\n    std::cout << "d = " << &d << \'\\n\';\n    std::cout << "c1 = " << c1 << \'\\n\';\n    std::cout << "c2 = " << c2 << \'\\n\';\n    std::cout << "bv1 = " << bv1 << \'\\n\';\n    std::cout << "bv2 = " << bv2 << \'\\n\';\n    std::cout << "bn1 = " << bn1 << \'\\n\';\n    std::cout << "bn2 = " << bn2 << \'\\n\';\n    std::cout << "b1 = " << b1 << \'\\n\';\n    std::cout << "b2 = " << b2 << \'\\n\';\n    std::cout << "b3 = " << b3 << \'\\n\';\n    std::cout << "b4 = " << b4 << \'\\n\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的输出:

\n\n
d = 0x7fff5ca18998\nc1 = 0x7fff5ca18998\nc2 = 0x7fff5ca189a0\nbv1 = 0x7fff5ca18998\nbv2 = 0x7fff5ca189a0\nbn1 = 0x7fff5ca18998\nbn2 = 0x7fff5ca189a0\nb1 = 0x7fff5ca189a8\nb2 = 0x7fff5ca18998\nb3 = 0x7fff5ca189a8\nb4 = 0x7fff5ca189a0\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

如果是(2),那么说“对于类格中基类的每次出现,都有一个相应的基类子对象”难道还不够吗?也就是说,如果晶格的构造已经依赖于虚拟和非虚拟基类关系来选择边和顶点?

\n
\n\n

合并您的建议...

\n\n
\n

包含关键字virtual 的基类说明符,\n 指定虚拟基类。对于每个清楚的\n 出现一个非虚拟的类格中的基类\n 对于最派生的类,最派生的对象 (1.8) 应\n 包含有一个对应的清楚的\n 基类子对象那种类型的对于指定为虚拟的每个不同的基类,最接近的派生对象应包含该类型的单个基类子对象。

\n
\n\n

我不是标准语言的专家。但是,当我阅读您修改后的规范时,我不明白如何:

\n\n
class V { /\xe2\x88\x97...\xe2\x88\x97/ };\nclass A : virtual public V { /\xe2\x88\x97 ... \xe2\x88\x97/ };\nclass B : virtual public V { /\xe2\x88\x97 ... \xe2\x88\x97/ };\nclass C : public A, public B { /\xe2\x88\x97...\xe2\x88\x97/ };\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果如图 4 所示:

\n\n
   V\n  / \\\n /   \\\nA     B\n \\   /\n  \\ /\n   C\n
Run Code Online (Sandbox Code Playgroud)\n\n

我没有看到标准中的另一处指定虽然V在下面的类层次结构中出现两次,但由于使用了关键字,实际上C只存在一个类型的子对象。Vvirtual

\n