2009-11-05 183 views
9

如果我有C++:C++虛函數的實現?

class A { 
    private: virtual int myfunction(void) {return 1;} 
} 

class B: public A { 
    private: virtual int myfunction(void) {return 2;} 
} 

然後,如果我從myfunction定義class B刪除virtual,這是否意味着,如果我有一個基於class Bclass C,我不能覆蓋myfunction,因爲它會靜態編譯?

另外,我很困惑,當你在公共場合切換時會發生什麼,而在這裏是私人的。如果我將myfunction中的class B的定義更改爲公開(並且class A中的那個保持私密),這是否是我不應該這樣做的嚴重錯誤?我認爲虛擬功能需要保持相同的類型,這是非法的,但請讓我們知道這是不對的。

謝謝!

+5

不需要爲派生類方法顯式編寫「虛擬」關鍵字。你可以忽略它,但它是一個很好的風格。 – varnie 2009-11-05 11:11:49

回答

15

'虛擬'的第一個定義是重要的定義。從基礎開始的這個函數是從虛擬派生出來的,這意味着對於重新實現的虛擬函數調用你不需要'虛擬'。如果基類中的函數簽名不是虛擬的,而是在派生類中是虛擬的,那麼基類沒有多態行爲。

class Base 
{ 
    public: 
    void func(void){ printf("foo\n"); } 
}; 
class Derived1 : public Base 
{ 
    public: 
    virtual void func(){ printf("bar\n"); } 
}; 
class Derived2 : public Derived1 
{ 
    public: 
    /* reimplement func(), no need for 'virtual' keyword 
     because Derived1::func is already virtual */ 
    void func(){ printf("baz\n"); } 
}; 

int main() 
{ 
    Base* b = new Derived1; 
    Derived1* d = new Derived2; 

    b->func(); //prints foo - not polymorphic 
    d->func(); //prints baz - polymorphic 
} 
+0

謝謝,這非常有幫助! – ash 2009-11-05 11:22:14

+0

不客氣。我還應該補充一點,「Base * b」實際上是Derived1。使用dynamic_cast在您需要的情況下執行安全的向下轉換。 – 2009-11-05 11:28:43

+0

但作者的例子涵蓋了私人成員。 – bua 2009-11-05 12:49:34

1

如果您從在B類的myfunction定義virtual

編譯器將增加這個要求。爲多態類型填寫V-Table。

!!但是!!

你將只能訪問類A的公有成員(B類:公共A)

的定義:

class B: private A 
{ 

} 

將導致A類的所有(包括公共)成員,將成爲B類私人用戶。 簡化您無法訪問A公衆會員。

要解決你可以聲明一些朋友:

class A 
{ 
    private: 
     friend class B; 
} 

更偉大的信息HERE

+0

感謝您的快速回復! – ash 2009-11-05 11:23:30

+0

答案對我來說有點困惑。從答案中我看出,B班不能訪問他從A班繼承的公共成員,然後通過宣佈A的B朋友來解決。我不認爲這是正確的。 B可以訪問A的公共和受保護成員,但B的用戶不能訪問A的公共成員,這不會由朋友聲明來解決。我錯過了什麼? – stefaanv 2009-11-05 12:04:49

+0

是的,您錯過了我的示例中的私有繼承。 – bua 2009-11-05 12:52:21

7

一旦一個函數在基類中變爲虛擬的,它將對每個其他子類都是虛擬的。

public,protected和private不影響函數的虛擬性質。

+0

謝謝!感謝您的知名度信息。 – ash 2009-11-05 11:24:10

+0

通過使您的虛擬功能受到保護或私人化,您可以向您的課程的用戶提示是否需要在子類中調用它們。 http://www.gotw.ca/publications/mill18.htm – 2010-04-09 09:10:01

0

virtual的行爲是它影響該方法時,你有一種類型的指向一個亞型的對象的指針被調用。例如:

B* obj = new B; 
A* base = obj; 

當你調用obj->myfunction()發生取決於A是否宣佈myfunction是虛擬的。如果它不是虛擬的,推理是:我們有一個類型爲A的指針,所以我們調用A中定義的函數,結果爲1。然而,如果Amyfunction定義爲虛擬的,則基於實際對象的類型而不是指針的類型在運行時執行查找;由於對象實際上是B,因此使用在B中定義的實現,結果爲2.

更多信息可在the C++ FAQ Lite section on virtual functions中找到。