2016-08-02 119 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" 

到底,如何用派生類構造函數初始化一個基類指針?

+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從類Base公開派生,所以指向的新對象是一個基礎(同時也是派生的)。

0

對於表達...

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

...的編譯看到的指針的Base實例對象。它尋找一種叫做Method1的方法。它發現它是非虛擬的方法的。所以它會靜態地綁定它(也就是在編譯時)並生成「直接」調用Base::Method1的代碼。

對於表達...

obj->Method2(); 

...編譯器看到的指針的Base實例對象。它尋找一種叫做Method2的方法。它發現它是一個虛擬方法。所以它不會靜態地綁定它(也就是在編譯時),但是會生成代碼,用於運行時查找實例對象obj指向的實際類。在運行時間有一個Derived的實例對象。因此Derived::Method2將被找到並執行。

讓我們總結了與偉大阿蘭凱的報價:

其實我提出了術語「面向對象」,我可以告訴你,我沒有C++的初衷。

相關問題