2011-09-12 56 views
1

說類B派生自類A。這兩個申報f()。 f受到保護。因此f只會在AB之內被調用。 f()需要聲明爲虛擬嗎?虛擬不必要的保護功能

或者說:說C來自B來自ABA聲明受保護的非虛擬f()。請撥打f()CB解決B::f()和在A到A::f()

在這種情況下,我們應該總是避免虛擬受保護的成員有靜態解決?這是否自動完成?謝謝!

+2

如果你用代碼來寫而不是散文,那會更好。 – PlasmaHH

+0

感興趣的內容:http://www.gotw.ca/publications/mill18.htm – Flexo

回答

1

當您需要多態行爲(此示例爲Template Method pattern)時,聲明受保護的方法virtual是必要的,當您不需要時應避免。然而,在後一種情況下,你不應該用另一個在子類中具有相同簽名的函數來遮蔽函數,否則你會感到令人費解的行爲(就像你在第2段中描述的那樣),這就爲微小的錯誤提供了可能性。

+0

這種情況下,多態行爲是什麼?是不是假設有一個指向基類的指針?那麼這不是按照定義要求公共功能訪問嗎? – Cookie

+0

@Cookie號在每個函數中,你調用A(從外部)或者你沒有在C或B中重載/重載,'this'是一個指向A的指針,所以只有A方法是已知的,如果調用的方法不是虛擬的,則它在運行時不會被解析,您將得到A方法。 –

+0

@Cookie,不,它不需要公共訪問。考慮'A'中的公共方法調用'A'中聲明的'protected virtual'方法,並在不同的子類中覆蓋。您可以通過'protected'方法獲得多態行爲。有關更多詳細信息,請參閱上面對* Template Method *的參考。 –

0

我在我的C有點生疏++,但我要說的是,當你聲明的方法private,因此你需要virtual在您的方案protected在一起「靜態解析」只會保證...

+1

你實際上可以有[私人虛擬功能](http:// stackoverflow。com/questions/2170688/private-virtual-method-in-c),它們將被動態綁定。在Java和C#,IIRC中,私有實際上是不可覆蓋的,因此是靜態綁定的。 – eran

2

由於只要調用f()是在A(而不是過載/在BC中重新實現)的函數中完成的,則this指針將解析爲A*,因此調用A::f()。所以不行,在這種情況下你仍然需要一個虛函數。

0

所以:

class A { 
public: 
    void f() { std::cout << "A::f\n"; } 
}; 

class B : public A { 
public: 
    void f() { std::cout << "B::f\n"; } 
}; 

只要編譯器知道的對象實際上是一個B,它會調用F()的B.但是,這並不總是這樣:

void callF(A* a) 
{ 
    a->f(); 
} 

B b; 
callF(&b); // prints A::f 

如果您想讓callF等功能調用正確的f()函數,請將其設爲virtual。通常,如果在後代類中重寫它們是有意義的,則可以使函數具有虛擬性。受保護的功能通常是這種情況。

+0

對不起,但這個例子假設'f()'是公開的。 – Cookie