ホームページ >バックエンド開発 >C#.Net チュートリアル >C++ 仮想メンバー関数と動的バインディングの詳細な説明

C++ 仮想メンバー関数と動的バインディングの詳細な説明

hzc
hzc転載
2020-07-01 15:33:062103ブラウズ

推奨学習: 「c チュートリアル

——コンパイラは非仮想メソッド (コンパイル時) に静的バインディングを使用します。マッチング )、仮想メソッドに動的バインディング (ランタイム マッチング) を使用します。

  • 仮想メソッドが使用されていない場合、ポインターの型はコンパイル時に判明するため、コンパイラはコンパイル時にメンバー メソッドを対応するクラスに関連付けることができます。静的バインディング;
  • 仮想メソッドを使用する場合、通常、オブジェクトの型はプログラムの実行時にのみ決定できるため、コンパイラによって生成されたコードは、実行時にメンバー関数を対応するクラスに関連付けます。プログラムが実行されます。これは動的バインディングと呼ばれます。

静的バインディングは動的バインディングよりも効率的です。

仮想関数の仕組み。

仮想関数。

メンバー関数を再定義します (関数のシグネチャを変更します)。

オーバーロードされたメンバー関数を再定義します。

効率

# プログラムが実行段階で決定を下すためには、何らかのメソッドを使用して、指定されたオブジェクトのタイプを追跡する必要があります。基本クラスのポインターまたは参照によって変換され、追加の処理オーバーヘッドが追加されます。したがって、次の状況は静的バインディングにより適しています:

  • クラスは基本クラスとして使用されません
  • 派生クラスは基本クラス

# のメソッドを再定義しません。したがって、静的バインディングが C のデフォルトの選択肢として設定されます。

基本クラスのメソッドを派生クラスで再定義する場合は、それを仮想メソッドに設定し、そうでない場合は、非仮想メソッドに設定します。

仮想関数の仕組み

コンパイラが仮想関数を処理する方法は、各オブジェクトに隠しメンバーを追加することです。隠しメンバーには、関数アドレス配列へのポインターが格納されます。この配列は仮想関数テーブル (vtbl) と呼ばれ、クラス オブジェクトに対して宣言された仮想関数のアドレスを格納します。

派生クラス オブジェクトには、独立したアドレス テーブルへのポインターが含まれます (つまり、新しいテーブルが作成されます)。 (メモリオーバーヘッドの増加)

仮想関数を呼び出すとき、プログラムはオブジェクトに格納されている vtbl アドレスを調べ、次に対応する関数アドレス テーブルを参照して、そのアドレスを検索します。テーブル。 (実行速度に影響)

つまり、仮想関数を使用すると、メモリと実行速度に一定のコストがかかります。たとえ非関数の方が仮想関数よりもわずかに効率的であるとしても、そうではありません。動的連携、編集機能あり。

コンストラクターを仮想関数にすることはできません。

クラスが基本クラスである必要がない場合を除き、デストラクターは仮想関数である必要があります。

フレンド関数はクラスのメンバーではなく、メンバーのみが仮想関数になることができるため、フレンド関数を仮想関数にすることはできません。

派生クラスが関数を再定義しない場合、関数の基本クラス バージョンが使用されます (継承されます)。派生クラスが派生チェーン内にある場合、基本クラスのバージョンが非表示になっていない限り、最新の仮想関数バージョン (ポインターまたは参照呼び出し) が使用されます。

再定義すると基本クラスのメソッドが非表示になります:

class Dwelling
{public:    virtual void showperks(int a) const;
    ...
};class Hovel : public Dwelling
{public:    virtual void showperks() const;
    ...
}

派生クラスで関数を再定義すると (パラメーターのシグネチャを変更すると)、非表示になります A基本クラスのメソッドをオーバーロードするのではなく、同じ名前の基本クラスのメソッドを使用します。

Hovel trump;
trump.showperks();    // validtrump.showperks(5);    // invalid

継承メソッドを再定義する場合は、それが元のプロトタイプとまったく同じであることを確認してください。戻り値の型が基本クラスの参照またはポインターの場合、派生クラスへの参照またはポインターに変更できます (戻り値の型の共分散。つまり、クラス型の変更に応じて戻り値の型の変更が許可されます)。

基本クラスの宣言がオーバーロードされている場合は、すべての基本クラスのバージョンを派生クラスで再定義する必要があります。1 つのバージョンのみが定義されている場合、他のバージョンは非表示になります。クラス オブジェクトは非表示になります。それらを使用できるようになります。

class Dwelling
{public:    virtual void showperks(int a) const;    virtual void showperks(double x) const;    virtual void showperks() const;
    ...
};class Hovel : public Dwelling
{    virtual void showperks(int a) const;    virtual void showperks(double x) const;    virtual void showperks() const;
    ...
};

変更が必要ない場合、新しい定義は基本クラスのバージョンのみを呼び出すことができます:

<span class="cnblogs_code"><span style="color: #0000ff;">void </span> 住居::showperks()<span style="color: #0000ff;">const</span> {住居::showperks();}</span>

以上がC++ 仮想メンバー関数と動的バインディングの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。