c++のvtordispドメイン

2338 ワード

仮想的に継承されたC++オブジェクトメモリレイアウトには、MSDNでこのように説明されている4バイトのvtordispフィールドがあることに注意します.
Enables the addition of the hidden vtordisp construction/destruction displacement member. The vtordisp pragma is applicable only to code that uses virtual bases. If a derived class overrides a virtual function that it inherits from a virtual base class, and if a constructor or destructor for the derived class calls that function using a pointer to the virtual base class, the compiler may introduce additional hidden “vtordisp” fields into classes with virtual bases.
すなわち、仮想継承で派生クラスがベースクラスの虚関数を書き換え、コンストラクション関数または解析関数でベースクラスを指すポインタを使用して関数を呼び出すと、コンパイラは虚ベースクラスにvtordispドメインを追加します.
#include <iostream>
using namespace std;

class Point
{
public:
	Point(int x=1, int y=1):_x(x),_y(y){}
	virtual void print(){cout << "This is Point. ";}
protected:
	int _x, _y;
};

class Point3d:virtual public Point
{
public:
	Point3d():_z(2){}
	void print(){cout << "This is Point3d. ";}
protected:
	int _z;
};


int main()
{
	Point3d d;
	int *p = (int *)&d;
	p++;
	cout << *p << endl;//  _z  2
	p++;
	cout << *p << endl; //  vtordisp  ,   0
	p++;
	cout << *p << endl; //  vptr  

	p++;
	cout << *p << endl;//  _x   1

	p++;
	cout << *p << endl; //  _y  1

	cout << sizeof(Point3d) << endl; //   24
	system("pause"); 
	return 0;
}<span style="color:#ff0000;">
</span>

上の説明:vs 2010の仮想継承では、派生クラスがベースクラスの虚関数を書き換え、派生クラスに宣言を表示する構造関数がある限り、vtordispドメインが追加され、devc++のPoint 3 dのサイズは20であり、vtordispが追加されていないことを示している.
このプログラムはVC++の悪境でこのような出力結果であり,g++コンパイル後,
g++では出力結果が異なり,各クラスの大きさが異なる.これは、コンパイラが仮想継承を記録する方法に関係します.
.
VC++はオフセット量を記録することによって仮想ベースクラスの位置を見つける.したがって、クラスではオフセット量が一定バイトを占めます.g++はオフセット量を虚関数テーブルに記録し、虚関数テーブルにオフセット量が正則的に格納されているのは虚関数アドレスである.オフセット量が負に格納されているのは、仮想ベースクラスのオフセット量です.
.
したがって,g++上の仮想継承下のクラスのサイズはVC++コンパイルのプログラムよりも小さい.
すなわちvs 2010では、満足:1.虚継承;2.派生クラスは親クラスの虚関数を書き換えた.3.宣言されたコンストラクション関数またはコンストラクション関数が表示され、サブクラスにvtordispドメインが追加されます.
参考記事:
http://www.cnblogs.com/fanzhidongyzby/archive/2013/01/14/2860015.html
http://technet.microsoft.com/zh-cn/sysinternals/7sf3txa8(v=vs.80)