我很新于CPP,正在学习关于后期绑定多态性的知识。
根据我所读和了解的,virtual关键字用于实现后期绑定。在编译时会创建一个由vptr指向的虚函数表。举个例子,
class BASE{
public:
virtual void f1(){cout<<"BASE F1\n";}
virtual void f2(){cout<<"BASE F2\n";}
void f3(){cout <<"BASE F3\n";}
};
class D1:public BASE{
public:
virtual void f1(){cout<<"D1 F1\n";}
void f2(){cout<<"D1 F2\n";}
};
class DD1:public D1{
public:
void f1(){cout<<"DD1 F1\n";}
void f2(){cout <<"DD1 F2\n";}
};
在这里,基类将在其虚表中具有2个函数:
BASE::f1()
BASE::f1()
D1是从BASE继承而来的,将会继承vtable:
D1::f1()
BASE::f1
DD1继承自D1,在其内部不会有任何vtable。
当我们创建一个对象时:
//case 1:
BASE *b = new D1();
b->f1();//will print "D1 F1"
b->BASE::f1();//will print "BASE F1"
b->f2();//will print "D1 F2"
//case 2:
BASE *b1 = new DD1();
b1->f1();//will print "DD1 F1"
b1->D1::f1();//will print "D1 F1"
b1->BASE::f1();//will print"BASE F1"
但是,在这种情况下: b1->D1::f1(); 会导致编译错误。
error: ‘D1’ is not a base of ‘BASE’
问题:为什么不应该打印D1 F1作为其虚函数。
在查看fdump后,我发现了更有趣的事情,它有点令人困惑;
Vtable for BASE
BASE::_ZTV4BASE: 4u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI4BASE)
16 (int (*)(...))BASE::f1
24 (int (*)(...))BASE::f2
Class BASE
size=8 align=8
base size=8 base align=8
BASE (0x7fbc3d2ff120) 0 nearly-empty
vptr=((& BASE::_ZTV4BASE) + 16u)
Vtable for D1
D1::_ZTV2D1: 4u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI2D1)
16 (int (*)(...))D1::f1
24 (int (*)(...))D1::f2
Class D1
size=8 align=8
base size=8 base align=8
D1 (0x7fbc3d31f2d8) 0 nearly-empty
vptr=((& D1::_ZTV2D1) + 16u)
BASE (0x7fbc3d2ff180) 0 nearly-empty
primary-for D1 (0x7fbc3d31f2d8)
Vtable for DD1
DD1::_ZTV3DD1: 4u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI3DD1)
16 (int (*)(...))DD1::f1
24 (int (*)(...))DD1::f2
Class DD1
size=8 align=8
base size=8 base align=8
DD1 (0x7fbc3d31f3a8) 0 nearly-empty
vptr=((& DD1::_ZTV3DD1) + 16u)
D1 (0x7fbc3d31f410) 0 nearly-empty
primary-for DD1 (0x7fbc3d31f3a8)
BASE (0x7fbc3d2ff1e0) 0 nearly-empty
primary-for D1 (0x7fbc3d31f410)
问题:Class BASE的虚拟表是否会被Class D1继承,Class D1的虚拟表和Class BASE会被DD1继承吗?虚拟表的继承将如何进行?
D1
中的f2
与f1
一样被覆盖,DD1
中的两个函数也是如此。 - molbdnilo