C++ 虚继承与继承的差异
上一篇 /
下一篇 2012-10-10 13:58:44
/ 个人分类:C++
%K\\vZH3?2E2V0 前面一篇文章,说明了在C++ 虚继承对基类构造函数调用顺序的影响。经过仔细推敲,发现没有彻底说清楚虚继承与普通继承之间的关系。所以用下面的文字再说明一下。51Testing软件测试网/A4S'v$EA:pi(O
)N.iC
x#I@@ kY0 首先,重复一下虚拟继承与普通继承的区别有:
:sTB#g.d
A0bap0?KD[f:@7F*x0 假设derived 继承自base类,那么derived与base是一种“is a”的关系,即derived类是base类,而反之错误;51Testing软件测试网 Y)b
d:A~^
#r(B(U7w~1J
m
q0 假设derived 虚继承自base类,那么derivd与base是一种“has a”的关系,即derived类有一个指向base类的vptr。
R8i4I[X[0[hx051Testing软件测试网s:^vx!M
R 因此虚继承可以认为不是一种继承关系,而可以认为是一种组合的关系。因为虚继承有着“继承”两个关键字,那么大部分人都认为虚继承与普通继承的用法没什么太大的不同。由此用在继承体系中,这种将虚继承认为是普通继承的危害更佳大。下面先用一个例子来说明问题:51Testing软件测试网'Yv(`.I6A3`
z6_7neR0class base 2a/L;}y ]/L~_*m0{ 'T!`:ay:ikzu0public:51Testing软件测试网\eQdI
|E base(){cout<<"base::base()!"<<endl;}51Testing软件测试网a-n2Yo1Q c#FAX void printBase(){cout<<"base::printBase()!"<<endl;}51Testing软件测试网9Y
x&J7^?0^7v b };51Testing软件测试网k TV#qwC 51Testing软件测试网/~pl&R
Rjclass derived:public base x9m-W0Q_2^B0{51Testing软件测试网M,U4Aj"S7CN [ public: g\#y-P~,~_-f?0 derived(){cout<<"derived::derived()!"<<endl;}51Testing软件测试网*[%K8w)|8g_3Z/b void printDerived(){cout<<"derived::printDerived()!"<<endl;} /|L:n9T2l,Z]i0}; !mQ%G$q"YAGp0 |
I%o4aw'l
M/AAy0 上面是普通继承实现,在实际应用中,我们可以使用下面的代码进行类型转换:51Testing软件测试网`}z!T s1Ql,u
int main(int argc, const char * argv[])51Testing软件测试网I1v
mfp3j)Oc[ { aC j#Zv2rT0 derived oo;51Testing软件测试网@
Q2K+Q
V&{t base oo1(static_cast<base>(oo));51Testing软件测试网(\,q?ojp
bG9G {5u]^sl oo1.printBase();
d?7?-YHd D-T0 derived oo2 = static_cast<derived&>(oo1); 1l C wY#B&DJ&g/^by'{0 oo2.printDerived();51Testing软件测试网E%{h2S)WH;_8q return 0;51Testing软件测试网d$X/I$hJ } |
51Testing软件测试网i.cH?
[)N1E 编译无错误,而且会得出正确的结果。其结果为:51Testing软件测试网FIq3d%iVVuY3k
51Testing软件测试网_3p l3`3VAJ0FB!^ base::base()!51Testing软件测试网bU5}wg~#S
m
derived::derived()!51Testing软件测试网[3}!Lr{W&pj
base::printBase()!
7j^&tyb0 derived::printDerived()!51Testing软件测试网3rP8dx(X Gg*Np0]
51Testing软件测试网.?o D!U&b5s}%\ 而将上面的普通继承变成虚拟继承,如下代码:51Testing软件测试网pNWO8ux0M
7U-U4F
Y*E0class base1 H*V\;\r0NL
X0{51Testing软件测试网!v
z@z$[l"x1J public:51Testing软件测试网-x:c h%f3x,A,M base1(){cout<<"base::base()!"<<endl;}51Testing软件测试网 ts@'` J void printBase(){cout<<"base::printBase()!"<<endl;} ~Pb{jTw0};51Testing软件测试网x(C"c4T:D.o$N1@ 51Testing软件测试网YFEkS'Fh1Nclass derived1:virtual public base1 %Y0O~CuU i;m%h0{ -R#v4XQ%{"j[U0public:51Testing软件测试网b^~!h}.i derived1(){cout<<"derived::derived()!"<<endl;}51Testing软件测试网Yu)\h*`;z Y:b4Cd&[ void printDerived(){cout<<"derived::printDerived()!"<<endl;} /f1x4c!x1Y9k}$M;j0}; /h
j4UV)Z07Ux6?2Y$ub.?/e*M0int main(int argc, const char * argv[]) h_1t t'xX0{51Testing软件测试网 H,J
{wM6Ys/m derived1 oo;51Testing软件测试网8u*o-v3R?(P base1 oo1(static_cast<base1>(oo));51Testing软件测试网5M3X5j7Z{g|"qI oo1.printBase();51Testing软件测试网] VKoq-L!a)c{ derived1 oo2 = static_cast<derived1&>(oo1);51Testing软件测试网+JwI\] oo2.printDerived(); :P K!Q
X(I6UV:NX}9DX0 return 0;51Testing软件测试网!LLt4~y@(wBJu }51Testing软件测试网8NKB9Q)x.]s n |
] _4B9jk@0 编译上面的代码,提示如下:51Testing软件测试网d"`4S[
|8B}
51Testing软件测试网w
r$kj]As
bI
可以看到不能将基类通过static_cast转换为继承类。我们知道c++提供的强制转换函数static_cast对于继承体系中的类对象的转换一般是可行的。那么这里为什么就不可以了呢?还是需要从虚拟继承的内部实现来说明问题。
a!VP#Q2jLX0
virtual base class的原始模型是在class object中为每一个有关联的virtual base
class加上一个指针vptr,该指针指向virtual基类表。有的编译器是在继承类已存在的virtual
table直接扩充导入一个virtual base class
table。不管怎么样由于虚继承已完全破坏了继承体系,不能按照平常的继承体系来进行类型转换。51Testing软件测试网{_l H`
不管怎么样,虚继承在类型转换是一定要十分注意。不要轻易使用虚继承,更不要在虚继承的基础上进行类型转换,切记切记!
!we {8lSN?0
收藏
举报
TAG: