C ++多型(IV)説明---のvtable

C ++多型

C ++は、多型(C)が知られている、関数テーブルの仮想アドレスポインタ(vfptr)、オブジェクトの仮想関数テーブルへアクセスすることによって、メモリ・モデル・オブジェクトに格納されています。

class Base
{
public:
	virtual void f(){ cout << "Base::f()" << endl; }
	virtual void g(){ cout << "Base::g()" << endl; }
	virtual void h(){ cout << "Base::h()" << endl; }

private:
	int _b1 = 1;
	int _b2 = 2;
};

オブジェクトb、B&Bの基本クラスは、メモリ内のアドレスです。
ここに画像を挿入説明

一般的な継承での仮想関数テーブル

通常の継承、ベースと発生する可能性があり、派生クラスの仮想関数カバレッジの下では、自分の仮想関数があるかもしれません。

一般的な継承(非仮想関数のオーバーライド)

以下は、継承のカバーなし関数、継承階層ないカバレッジです。

class Base
{
public:
	virtual void f(){ cout << "Base::f()" << endl; }
	virtual void g(){ cout << "Base::g()" << endl; }
	virtual void h(){ cout << "Base::h()" << endl; }

private:
	int _b1 = 1;
	int _b2 = 2;
};

class Derived : public Base
{
public:
	virtual void f1(){ cout << "Derived::f1()" << endl; }
	virtual void g1(){ cout << "Derived::g1()" << endl; }
	virtual void h1(){ cout << "Derived::h1()" << endl; }
};

ここに画像を挿入説明
派生クラス仮想関数続いて、仮想関数の前に基底クラスの仮想関数テーブルに、派生クラスの仮想関数テーブルを見つけることができる(VS2013で実行)を0に、仮想関数テーブル終端フラグです。
ここに画像を挿入説明

一般承継(カバーは、仮想関数を持っています)
class Base
{
public:
	virtual void f(){ cout << "Base::f()" << endl; }
	virtual void g(){ cout << "Base::g()" << endl; }
	virtual void h(){ cout << "Base::h()" << endl; }

private:
	int _b1 = 1;
	int _b2 = 2;
};

class Derived : public Base
{
public:
	virtual void f(){ cout << "Derived::f()" << endl; } //存在覆盖的情况
	virtual void g1(){ cout << "Derived::g1()" << endl; }
	virtual void h1(){ cout << "Derived::h1()" << endl; }
};

ここに画像を挿入説明
、、()メンバ関数F基底クラスカバーにおける派生クラスF()メンバ関数を見つけることができる仮想関数テーブルは、我々は、少なくとも一つのアドレス、派生クラスを参照して、アドレスがポイントの関数であってもよいです発見した派生クラスの仮想基底クラスの仮想関数機能をカバーするものの欠如
ここに画像を挿入説明

多重継承での仮想関数テーブル

カバー無し多重継承機能しません

ここに画像を挿入説明
最初のベースクラスの派生クラスの仮想関数、それぞれの仮想機能自体を格納する仮想関数テーブルの残りの部分

多重継承の存在をカバーする機能
class Base1
{
public:
	virtual void f(){ cout << "Base::f()" << endl; }
	virtual void g(){ cout << "Base::g()" << endl; }
	virtual void h(){ cout << "Base::h()" << endl; }
};

class Base2
{
public:
	virtual void f(){ cout << "Base::f()" << endl; }
	virtual void g(){ cout << "Base::g()" << endl; }
	virtual void h(){ cout << "Base::h()" << endl; }
};

class Base3
{
public:
	virtual void f(){ cout << "Base::f()" << endl; }
	virtual void g(){ cout << "Base::g()" << endl; }
	virtual void h(){ cout << "Base::h()" << endl; }
};

class Derived : public Base1, public Base2, public Base3
{
public:
	virtual void f(){ cout << "Derived::f()" << endl; } //发生覆盖情况
	virtual void g1(){ cout << "Derived::g1()" << endl; }
	virtual void h1(){ cout << "Derived::h1()" << endl; }
};

多重継承、派生クラスのオブジェクト構造は、以下のように:
ここに画像を挿入説明
ここに画像を挿入説明
ここに画像を挿入説明
私たちは、サブクラスの仮想関数に置き換えられているテーブル()関数の三の親クラスの仮想関数fの位置を見ることができます。
サブクラス意志仮想関数呼び出しサブクラスへの任意の静的タイプの親ポインタ

Derive d;
Base1 *b1 = &d;
Base2 *b2 = &d;
Base3 *b3 = &d;
b1->f(); //Derive::f()
b2->f(); //Derive::f()
b3->f(); //Derive::f()
公開された52元の記事 ウォン称賛26 ビュー3408

おすすめ

転載: blog.csdn.net/weixin_43796685/article/details/103717151