ホームページ >バックエンド開発 >C++ >基本クラスのコンストラクターで仮想関数を呼び出すと、基本クラスの実装が使用されるのはなぜですか?

基本クラスのコンストラクターで仮想関数を呼び出すと、基本クラスの実装が使用されるのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-12-21 02:03:15819ブラウズ

Why Does Calling a Virtual Function in a Base Class Constructor Result in the Base Class Implementation Being Used?

コンストラクターでの仮想関数のオーバーライド

次のコード スニペットを考えてみましょう:

#include <iostream>
struct base {
  virtual const int value() const {
    return 0;
  }

  base() { // Default constructor
    std::cout << value() << std::endl;
  }
};

struct derived : public base {
  virtual const int value() const {
    return 1;
  }
};

int main() {
  derived d; // Declares an instance of the derived class
}

このコードを実行すると、期待される 1 の代わりに 0 が出力されます。なぜですか?

構築中の仮想関数呼び出し

基底クラスのコンストラクターがコンストラクター内で仮想関数を呼び出すと、仮想関数はインスタンスではなく基底クラスのインスタンスで呼び出されます。派生クラスのインスタンス。これは、構築中のオブジェクトの「成熟」プロセスの結果です。

  • 成熟: オブジェクトが構築されると、基本クラスのコンストラクターから開始され、徐々に「成熟」します。

この例では、オブジェクトが部分的に構築されたときに、基本コンストラクターが value() を呼び出します。この時点では、オブジェクトはまだ派生オブジェクトに「成熟」していません。したがって、value() の元の基本実装が呼び出されます。

問題の修正方法

コードに 1 を出力させるには、仮想関数の呼び出しを回避できます。コンストラクター内で。これは次の方法で実現できます:

  1. ポインターの使用: メンバー関数から直接ではなく、基本クラスへのポインターまたは参照から仮想関数を呼び出します:

    base* b = new derived();
    b->value(); // Calls the derived class implementation
    
    delete b;
  2. メンバーの初期化の使用リスト: メンバー初期化リストを使用して、コンストラクターで仮想関数の値を明示的に指定します:

    derived d : base() { } // Initializes `base()` and the virtual function
                           // call to occur within the constructor
  3. 以上が基本クラスのコンストラクターで仮想関数を呼び出すと、基本クラスの実装が使用されるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。