2016-08-02 19 views
0

仮想関数を理解しようとしていて、次のコードに遭遇しました。派生クラスのコンストラクタを基本クラスのポインタに代入

class Base 
{ 
    public: 
      void Method1() { std::cout << "Base::Method1" << std::endl; } 
    virtual void Method2() { std::cout << "Base::Method2" << std::endl; } 
}; 

class Derived : public Base 
{ 
    public: 
    void Method1() { std::cout << "Derived::Method1" << std::endl; } 
    void Method2() { std::cout << "Derived::Method2" << std::endl; } 
}; 

Base* obj = new Derived(); 
    // Note - constructed as Derived, but pointer stored as Base* 

obj->Method1(); // Prints "Base::Method1" 
obj->Method2(); // Prints "Derived::Method2" 

最後に、派生クラスのコンストラクタでBaseクラスのポインタを初期化する方法を教えてください。

+2

関連:http://stackoverflow.com/questions/4937180/a-base-class-pointer-can-point-to-a-derived-class-object-why-is-the-vice-versa – NathanOliver

答えて

3

C++では、派生ポインタ型から基本ポインタ型への暗黙的キャストが可能です。これは、派生型のメモリレイアウトがベースクラスのサイズまでベースと同じであるため安全です。

あなたはobjという実数型のトラックを失ってしまっている可能性があるため、この例ではバグが発生する可能性があります。それを削除する時間が来たら、あなたは間違ったデストラクタを呼び出すでしょう。これは、デストラクタを仮想化することで救済することができます。発現のために

0

コンストラクタの呼び出しの結果で初期化されます。 新しいDerived()を呼び出すと、新しいDerivedオブジェクトへのポインタが作成されます。 クラスDerivedはクラスBaseから公開されているため、指し示された新しいオブジェクトは基底です(派生と同時に)。

0

...

obj->Method1(); // Prints "Base::Method1" 

... コンパイラBaseのインスタンスオブジェクトへのポインタを見ています。 Method1というメソッドを探します。それは非仮想メソッドとしてそれを見つける。したがって、コンパイル時に静的にバインドし、Base::Method1を直接呼び出すコードを生成します。発現のために

...

obj->Method2(); 

...コンパイラはBaseのインスタンスオブジェクトへのポインタを見ています。 Method2というメソッドを探します。それは仮想メソッドとしてそれを見つける。コンパイル時に静的にバインドしませんが、ランタイムのインスタンスオブジェクトの実際のクラスを参照するコードobjが生成されます。 ランタイムには、インスタンスオブジェクトDerivedがあります。したがって、Derived::Method2が見つけられ実行されます。

実は私は用語「オブジェクト指向」を作って、私は心の中でC++を持っていなかったあなたを伝えることができます。

はのは、偉大なアラン・ケイの引用であることを要約してみましょう。

関連する問題