2010-05-05 87 views
4

如果兩種方法都被聲明爲虛擬的,那麼被調用的Method1()的兩個實例都不應該是派生類的Method1()?關於虛擬方法的問題

我看到BASE然後派生每次調用。我正在爲面試做一些評估,我想確保我有這個直接。的xD

class BaseClass 
{ 
public: 
    virtual void Method1() { cout << "Method 1 BASE" << endl; } 
}; 

class DerClass: public BaseClass 
{ 
public: 
    virtual void Method1() { cout << "Method 1 DERVIED" << endl; } 
}; 


DerClass myClass; 
    ((BaseClass)myClass).Method1(); 
    myClass.Method1(); 

方法1個BASE
方法1 DERVIED

+0

「如果兩種方法都被聲明爲虛擬的,」 - 派生類中的覆蓋是虛擬的(儘管人們只是爲了清晰起見而將它添加),所以這與問題無關。 – UncleBens 2010-05-05 21:11:26

+1

你正在尋找的演員將是'((BaseClass&)myClass)。Method1();',或者多一點C++:'static_cast (myClass).Method1();' – GManNickG 2010-05-05 21:14:24

+0

另外,你應該避免使用C風格的類型轉換。 – rlbond 2010-05-05 21:14:26

回答

6

你在這裏看到的是"slicing"。將派生類的對象投射到基類中「切掉」不在基類中的所有內容。

在C++虛函數中,只能對指針或引用正確工作。對於示例工作的權利,你必須做到以下幾點:

 

DerClass myClass; 
((BaseClass *) &myClass)->Method1(); 

或者你可以做

 

BaseClass *pBase = new DerClass; 
pBase->Method1(); 
 
+0

Dima:+1不要忘記提及'在C++虛函數中只能正確工作指針或引用' – 2012-01-23 09:55:32

12

否,因爲如果一個功能通過指針或參考稱爲虛擬函數機制只。否則,使用該對象的靜態類型來確定要調用哪個函數。

+1

啊。謝謝大家的解釋! :D – bobber205 2010-05-05 21:19:59

5

由於投((BaseClass)myClass)切片myClass對象從DerClassBaseClass,所以只有BaseClass的實施Method1()被調用。

對於多態性正常工作,您必須通過指針調用的方法:

DerClass myClass; 
BaseClass* ptrToMyClass = &myClass; 
ptrToMyClass->Method1(); // Calls the DerClass implementation of Method1() 

或引用:

DerClass myClass; 
BaseClass& refToMyClass = myClass; 
refToMyClass.Method1(); // Calls the DerClass implementation of Method1() 
14

不, 「C風格」 投((BaseClass)myClass)創建一個臨時BaseClass對象由切片 myClass。它的動態類型是BaseClass,它根本不是DerClass,所以被調用的Method1是基類方法。

myClass.Method1()是一個直接調用。由於myClass是一個對象,而不是一個參考,所以沒有虛擬調度(不需要)。

+0

切片上的良好通話。要求考生明確區分C++還是說Java或C#,這總是一個很好的問題。 – 2010-05-06 00:57:11

0

((BaseClass的)MyClass的).Method1(); - >對象切片因此總是調用基類方法。 真正的多態行爲是通過可以包含派生類的任何對象的基類指針實現的。 因此,要實現你想要的東西,你需要做派生類對象的地址,並將它轉換爲基類指針。如下所示: ((BaseClass *)& myClass) - > Method1();