2011-11-02 81 views
0

我在虛函數和引用中有一個問題。當我嘗試準備面試時,這是一個難題。我谷歌一段時間,但不能看到確切的情況。參考類型轉換中的C++虛函數

代碼給出如下:

class A{ 
public: 
virtual void foo() {cout << "A::foo" << endl;} 
}; 

class B: public A{ 
public: 
void foo() {cout << "B::foo" << endl;} 
}; 

class C: public B{ 
public: 
void foo() {cout << "C::foo" << endl;} 
}; 

int main(void){ 
C c; 

B *q; 
q = &c; q->foo(); 
return 0; 
} 

我的想法來的輸出將是B :: foo的,但得到的答覆居然是C :: foo中。有人能告訴我爲什麼vtable不會選擇B的實現嗎?由於

+1

'q'指向'C'的一個實例,所以這就是被調用的'foo'的版本。你可以用你的理由更新你的問題*爲什麼*你認爲輸出是'B :: foo'? – Ayjay

+0

對不起,我應該提到這是在C++中的文章 – wilson100

回答

0

據我所知:

一旦虛函數表的使用 - 這是在這種情況下,由virtual聲明A::foo強制 - 這是你聲明什麼類型並不重要,它會隨時調用最具體方法的方法 - 這在這種情況下是C::foo

2

fooB中是虛擬的,因爲它覆蓋了基類中的虛函數,即使它沒有明確聲明爲virtual

最派生類型通過q->foo()稱爲對象的是CC的用於foo與簽名void foo()最終超控器是C::foo所以這是被調用的函數。

1

因爲q指向一個C對象,它的虛函數表包含一個虛函數foo。請記住,在任何派生類中,在類中聲明的任何虛函數都是虛擬的。這是使用基類訪問派生類的方法。

0

有人能告訴我爲什麼vtable不會選擇B的實現嗎?

這就是虛擬函數的重點,所以通過基類指針調用overriden方法仍然會調用派生類中的方法。

q類型爲B *,但它指向一個C對象。所以,當你調用虛函數foo()時,調用C::foo()實現。

即使foo()沒有標記virtualBC,它仍然是一個虛函數,因爲它是在A宣佈爲。

如果你想B::foo()被調用,你需要明確地調用它。

q->B::foo(); 
2

foo如果被虛擬的,則稱爲將基於指針的類型的功能,和B::foo()將被調用。

由於foo在基類中定義爲虛擬的,它在所有派生類中都保持虛擬。在這種情況下,被調用的函數是基於指向對象而不是指針的類型。由於對象指向的是C,因此調用的函數是C::foo()

0

foo()是一個虛擬函數,這意味着,在其實例是實際上指向q叫做而不是在指針的類型在該類中定義的一個類定義的版本。

請記住,一旦它被標記爲虛擬的地方了類層次結構,即一個需要沒有明確標記功能在B級和C再虛擬,因爲這已經在A級做了成員函數是虛擬的