說類B
派生自類A
。這兩個申報f()
。 f受到保護。因此f只會在A
和B
之內被調用。 f()
需要聲明爲虛擬嗎?虛擬不必要的保護功能
或者說:說C
來自B
來自A
。 B
和A
聲明受保護的非虛擬f()
。請撥打f()
C
和B
解決B::f()
和在A到A::f()
?
在這種情況下,我們應該總是避免虛擬受保護的成員有靜態解決?這是否自動完成?謝謝!
說類B
派生自類A
。這兩個申報f()
。 f受到保護。因此f只會在A
和B
之內被調用。 f()
需要聲明爲虛擬嗎?虛擬不必要的保護功能
或者說:說C
來自B
來自A
。 B
和A
聲明受保護的非虛擬f()
。請撥打f()
C
和B
解決B::f()
和在A到A::f()
?
在這種情況下,我們應該總是避免虛擬受保護的成員有靜態解決?這是否自動完成?謝謝!
當您需要多態行爲(此示例爲Template Method pattern)時,聲明受保護的方法virtual
是必要的,當您不需要時應避免。然而,在後一種情況下,你不應該用另一個在子類中具有相同簽名的函數來遮蔽函數,否則你會感到令人費解的行爲(就像你在第2段中描述的那樣),這就爲微小的錯誤提供了可能性。
這種情況下,多態行爲是什麼?是不是假設有一個指向基類的指針?那麼這不是按照定義要求公共功能訪問嗎? – Cookie
@Cookie號在每個函數中,你調用A(從外部)或者你沒有在C或B中重載/重載,'this'是一個指向A的指針,所以只有A方法是已知的,如果調用的方法不是虛擬的,則它在運行時不會被解析,您將得到A方法。 –
@Cookie,不,它不需要公共訪問。考慮'A'中的公共方法調用'A'中聲明的'protected virtual'方法,並在不同的子類中覆蓋。您可以通過'protected'方法獲得多態行爲。有關更多詳細信息,請參閱上面對* Template Method *的參考。 –
我在我的C有點生疏++,但我要說的是,當你聲明的方法private
,因此你需要virtual
在您的方案protected
在一起「靜態解析」只會保證...
你實際上可以有[私人虛擬功能](http:// stackoverflow。com/questions/2170688/private-virtual-method-in-c),它們將被動態綁定。在Java和C#,IIRC中,私有實際上是不可覆蓋的,因此是靜態綁定的。 – eran
由於只要調用f()
是在A
(而不是過載/在B
或C
中重新實現)的函數中完成的,則this
指針將解析爲A*
,因此調用A::f()
。所以不行,在這種情況下你仍然需要一個虛函數。
所以:
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
。通常,如果在後代類中重寫它們是有意義的,則可以使函數具有虛擬性。受保護的功能通常是這種情況。
對不起,但這個例子假設'f()'是公開的。 – Cookie
如果你用代碼來寫而不是散文,那會更好。 – PlasmaHH
感興趣的內容:http://www.gotw.ca/publications/mill18.htm – Flexo