私は CPP を初めて使用し、レイト バインディング ポリモーフィズムについて学んでいます。
私が読んで理解したことによると、仮想キーワードは遅延バインディングに使用されます。コンパイル時に内部的に vptr が指す vtable を作成します。たとえば、
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";}
};
ここで、BASE は基本クラスの vtable に 2 つの関数を持ちます。
BASE::f1()
BASE::f1()
BASE から継承する D1 には、vtable が継承されます。
D1::f1()
BASE::f1
D1 から継承する DD1 には、独自の 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をスローした後、もう 1 つ興味深いことがわかりました。
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)
質問: クラス BASE の仮想テーブルはクラス D1 に継承され、クラス D1 の vTable とクラス BASE は DD1 に継承されませんか? 仮想テーブルの継承はどのように行われますか?