2010-09-21 64 views
2
#include <iostream> 
using namespace std; 

class base 
{ 
public: 
    void f() {cout << "base" << endl;} 
    virtual void v() {cout << "base (virtual)" << endl;} 


}; 

class deriv : public base 
{ 
public: 
    void f() {cout << "deriv" << endl;} 
    void v() {cout << "deriv (overridden)" << endl;} 
}; 


int main() 
{ 
    base b; 
    b.f(); 
    b.v(); 

    deriv d; 
    d.f(); 
    d.v(); 
} 

我不明白這兩種方法之間有什麼真正的區別f和v:如果我用另一個名稱替換一個函數,我不是「替換」它嗎?即使我仍然可以通過創建一個base *指針來訪問它,然後將它指向一個deriv對象,我不明白這裏有什麼樣的「乾淨的」C++使用。同名繼承函數和重載虛函數有什麼區別?

當不使用虛擬(意思是可重寫的方法)方法時,有人可以告訴我這是否有合法用途,與使用重寫虛擬方法有什麼不同?

編輯:我很抱歉使用壞的語法與降價,但減價是一個非常糟糕的選擇,它很複雜,相當反覆無常(我更喜歡紡織赫赫)。 EDIT2:對不起,我沒猜錯101010101010101按鈕意味着插入代碼,我通常只是用手工:(做

+0

gokoon,SO使格式化代碼非常容易。標記你的代碼,點擊編輯框上方的'101010'按鈕,就完成了。什麼比這更容易? – sbi 2010-09-21 19:46:49

+0

如果您想開始Markdown和Textile之間的討論,請嘗試[meta SO](http://meta.stackoverflow.com)。 – BoltClock 2010-09-21 19:49:37

回答

6

關鍵是要得到polymorphic behavior如果在一個基類中的函數聲明爲虛擬的,和派生類中重寫它,如果你調用使用基地類指針的功能就會自動調用在派生類的功能。如果是虛擬的,那麼它會調用基類的功能。

基本的想法是,你可以這樣做:

class Animal 
{ 
    public: 
    virtual void talk() = 0; 
}; 

class Dog : public Animal 
{ 
    public: 
    void talk() { cout << "Bark" << endl; } 
}; 

class Cat : public Animal 
{ 
    public: 
    void talk() { cout << "Meow" << endl; } 
}; 

void foo(Animal* a) 
{ 
    a->talk(); 
} 

現在,當你傳遞一個動物指針foo()並調用talk()成員函數,這將取決於它是否指向Cat對象或Dog對象做不同的事情。問題是foo()可以使用從Animal繼承的任何內容。此外,如果稍後您創建一個新的Animal類,則可以將它傳遞給foo(),而不必修改foo()中的任何代碼。

4

當您使用指針或引用時,您只會看到兩者之間的差異。

deriv * d = new deriv; 
d->f(); // "deriv" 
d->v(); // "deriv (overridden)" 

正如所料。現在我們將此指針投射到基指針上:

base * b = static_cast<base *>(d); 
b->f(); // "base" 
b->v(); // "deriv (overridden)" 

即使指針是指向基類的指針,虛函數調用也會轉到派生函數。

+0

爲了完整起見,參考文獻具有相同的效果。 – doron 2010-09-21 20:13:55

+0

@doron,我在第一句話中說過。當然很容易錯過。 – 2010-09-21 20:47:01