オブジェクトの構造とダミーテーブル
6136 ワード
こんなクラスがあるとしたら
vsは親クラス,子クラスの虚表アドレスをコードセグメントに存在させる
コンストラクション関数とコンストラクション関数が呼び出されるたびに、それぞれのダミーテーブルアドレスが戻されます.
親プロファイル:
親構造:
サブクラス構造:
次の結論が得られます.
newのサブクラスの場合、コンパイラは親クラスと子クラスの虚表エントリアドレスをコードセグメントに保存し、親クラスと子クラスにはそれぞれ虚表があり、構築前に値を割り当てています(子クラスの前にいくつかの値がまだ不明です).
thisポインタはこの新しいクラスのアドレスを保存し,最初の4バイトは虚表のエントリアドレスを格納し,まず親クラスを構築し,親クラスの虚表エントリアドレスに値を付与する.上記の手順の例に従って、親サイズの領域を0にします.サブクラスを構築し,サブクラスのダミーテーブルエントリアドレスを書き込む.
解析の場合、底から上へ解析すると、コンパイラはまず本クラスの虚表エントリアドレスに値を割り当てます.これは、本クラスを正しく解析するためです.再割り当てしないと、サブクラスの関数を呼び出す可能性があるので、サブクラスはすでに解析が完了しています.
コンストラクションとコンストラクション関数では、コンストラクションとコンストラクションのたびにコンパイラがこのクラスの虚関数のエントリ値を再設定し、虚関数を呼び出すのは意味がないため、虚関数は使用できません.
1 class Base
2 {
3 public:
4 Base()
5 {
6 clear();
7 }
8 virtual ~Base()
9 {
10 int a = 0;
11 }
12 virtual void fun()
13 {
14 cout << "base" << endl;
15 }
16 void clear()
17 {
18 memset(this,0,sizeof Base);
19 }
20 int m_int32;
21 };
22 class child : public Base
23 {
24 public:
25 virtual ~child()
26 {
27 int a = 0;
28 }
29 virtual void fun()
30 {
31 cout << "child" << endl;
32 }
33 };
vsは親クラス,子クラスの虚表アドレスをコードセグメントに存在させる
コンストラクション関数とコンストラクション関数が呼び出されるたびに、それぞれのダミーテーブルアドレスが戻されます.
親プロファイル:
1 00411B36 mov dword ptr [eax],offset Base::`vftable' (417814h)
2 int a = 0;
3 00411B3C mov dword ptr [a],0
親構造:
00411976 mov dword ptr [eax],offset Base::`vftable' (417814h)
{
clear();
0041197C mov ecx,dword ptr [this]
0041197F call Base::clear (411127h)
}
サブクラス構造:
00411916 call Base::Base (411145h)
0041191B mov eax,dword ptr [this]
0041191E mov dword ptr [eax],offset child::`vftable' (417808h)
00411924 mov eax,dword ptr [this]
次の結論が得られます.
newのサブクラスの場合、コンパイラは親クラスと子クラスの虚表エントリアドレスをコードセグメントに保存し、親クラスと子クラスにはそれぞれ虚表があり、構築前に値を割り当てています(子クラスの前にいくつかの値がまだ不明です).
thisポインタはこの新しいクラスのアドレスを保存し,最初の4バイトは虚表のエントリアドレスを格納し,まず親クラスを構築し,親クラスの虚表エントリアドレスに値を付与する.上記の手順の例に従って、親サイズの領域を0にします.サブクラスを構築し,サブクラスのダミーテーブルエントリアドレスを書き込む.
解析の場合、底から上へ解析すると、コンパイラはまず本クラスの虚表エントリアドレスに値を割り当てます.これは、本クラスを正しく解析するためです.再割り当てしないと、サブクラスの関数を呼び出す可能性があるので、サブクラスはすでに解析が完了しています.
コンストラクションとコンストラクション関数では、コンストラクションとコンストラクションのたびにコンパイラがこのクラスの虚関数のエントリ値を再設定し、虚関数を呼び出すのは意味がないため、虚関数は使用できません.