jch*_*chl 13 c++ multiple-inheritance virtual-inheritance
我理解C++虚拟继承的基础知识.但是,我很困惑我需要在virtual
复杂的类层次结构中使用关键字.例如,假设我有以下类:
A
/ \
B C
/ \ / \
D E F
\ / \ /
G H
\ /
I
Run Code Online (Sandbox Code Playgroud)
如果我想确保在任何子类中都没有出现过多次类,那么需要标记哪些基类virtual
?他们都是?或者只在那些直接从一个类派生的类上使用它就足够了,否则这个类可能有多个实例(即B,C,D,E和F;以及G和H(但只有基类E,而不是基类D和F))?
Nor*_*ame 24
我一起玩弄了一个程序,可以帮助你研究虚拟基础的复杂性.它将类层次结构打印I
为适合graphiviz的图(http://www.graphviz.org/).每个实例都有一个计数器,可以帮助您了解施工顺序.这是程序:
#include <stdio.h>
int counter=0;
#define CONN2(N,X,Y)\
int id; N() { id=counter++; }\
void conn() \
{\
printf("%s_%d->%s_%d\n",#N,this->id,#X,((X*)this)->id); \
printf("%s_%d->%s_%d\n",#N,this->id,#Y,((Y*)this)->id); \
X::conn(); \
Y::conn();\
}
#define CONN1(N,X)\
int id; N() { id=counter++; }\
void conn() \
{\
printf("%s_%d->%s_%d\n",#N,this->id,#X,((X*)this)->id); \
X::conn(); \
}
struct A { int id; A() { id=counter++; } void conn() {} };
struct B : A { CONN1(B,A) };
struct C : A { CONN1(C,A) };
struct D : B { CONN1(D,B) };
struct E : B,C { CONN2(E,B,C) };
struct F : C { CONN1(F,C) };
struct G : D,E { CONN2(G,D,E) };
struct H : E,F { CONN2(H,E,F) };
struct I : G,H { CONN2(I,G,H) };
int main()
{
printf("digraph inh {\n");
I i;
i.conn();
printf("}\n");
}
Run Code Online (Sandbox Code Playgroud)
如果我运行this(g++ base.cc ; ./a.out >h.dot ; dot -Tpng -o o.png h.dot ; display o.png
),我会获得典型的非虚拟基础树:
alt text http://i34.tinypic.com/2ns6pt4.png
添加足够的虚拟......
struct B : virtual A { CONN1(B,A) };
struct C : virtual A { CONN1(C,A) };
struct D : virtual B { CONN1(D,B) };
struct E : virtual B, virtual C { CONN2(E,B,C) };
struct F : virtual C { CONN1(F,C) };
struct G : D, virtual E { CONN2(G,D,E) };
struct H : virtual E,F { CONN2(H,E,F) };
struct I : G,H { CONN2(I,G,H) };
Run Code Online (Sandbox Code Playgroud)
..钻石形状的结果(看数字来学习施工顺序!!)
替代文字http://i33.tinypic.com/xpa2l5.png
但是如果你把所有的基础虚拟化:
struct A { int id; A() { id=counter++; } void conn() {} };
struct B : virtual A { CONN1(B,A) };
struct C : virtual A { CONN1(C,A) };
struct D : virtual B { CONN1(D,B) };
struct E : virtual B, virtual C { CONN2(E,B,C) };
struct F : virtual C { CONN1(F,C) };
struct G : virtual D, virtual E { CONN2(G,D,E) };
struct H : virtual E, virtual F { CONN2(H,E,F) };
struct I : virtual G,virtual H { CONN2(I,G,H) };
Run Code Online (Sandbox Code Playgroud)
你得到一个具有不同初始化顺序的钻石:
alt text http://i33.tinypic.com/110dlj8.png
玩得开心!
virtual
从A,B,C和E类(位于菱形顶部)继承时,必须指定继承.
class A;
class B: virtual A;
class C: virtual A;
class D: virtual B;
class E: virtual B, virtual C;
class F: virtual C;
class G: D, virtual E;
class H: virtual E, F;
class I: G, H;
Run Code Online (Sandbox Code Playgroud)