2017-10-21 82 views
3

試圖快速瞭解virtual函數如何工作,但不確定爲什麼下面的代碼不打印任何輸出。據我所知,由於moveMouth()virtual,它應該使用talk類中的moveMouth()版本。C++虛函數簡單示例

/* 
* main.cpp 
* 
* Created on: Mar 29, 2015 
*  Author: Admin 
*/ 

#include <iostream> 

using namespace std; 

class talk{ 

public: 

    int a=5; 
    void moveMouth(){ 
     cout <<"blah blah blah"<<endl; 
    } 
}; 

class person : public talk { 

public: 
    int id; 
    person(int a): id(a) { 

    } 

    virtual void moveMouth(){ 
     //cout <<"word word word"<<endl; 
    } 


}; 

int main(){ 
    person* p = new person(0); 
    p->moveMouth(); 
    return 0; 
} 
+4

您需要將基類函數聲明爲虛函數 –

回答

1

沒有輸出,因爲虛函數機制允許調用通過指針或引用一個子類的功能,父母,不要從孩子調用父母的功能。

如果你想這種行爲那麼就是不申報的功能在所有的孩子:

class person : public talk { 

public: 
    int id; 
    person(int a) : id(a) { 

    } 

    //virtual void moveMouth(){ 
    // //cout <<"word word word"<<endl; 
    //} 


}; 

這將打印輸出,因爲繼承的函數將被調用。


這是根據所提供的代碼的虛擬函數機制的例子:

#include <iostream> 
#include <vector> 

using namespace std; 

class talk{ 

public: 

    int a = 5; 
    virtual void moveMouth(){ // base function is virtual 
     cout << "blah blah blah" << endl; 
    } 
}; 

class person : public talk { 

public: 
    int id; 
    person(int a) : id(a) { 

    } 
    void moveMouth() override { // override is optional but confirms we're overriding 
     cout <<"I'm a person"<<endl; 
    } 
}; 

class dog : public talk { 

public: 
    int id; 
    dog(int a) : id(a) { 

    } 
    void moveMouth() override { // override is optional but confirms we're overriding 
     cout <<"I'm a dog"<<endl; 
    } 
}; 

int main(){ 
    talk* p = new person(0); 
    talk* d = new dog(0); 
    p->moveMouth(); 
    d->moveMouth(); 

    std::vector<talk*> talkers; // can store pointers to all the different talkers in a single structure 
    talkers.push_back(p); 
    talkers.push_back(d); 
    for(auto i : talkers) 
     i->moveMouth(); 
    return 0; 
} 
2

您需要告訴基類虛函數。

即修改代碼,這

class talk{ 

public: 

    int a=5; 
    virtual void moveMouth(){ 
     cout <<"blah blah blah"<<endl; 
    } 
}; 

順便說一句,int a..應該是私有的 - 查找封裝

4

據我所知,因爲moveMouth()virtual,它應該使用版本moveMouth()talk類中。

不,這不是多態性的工作原理。它允許您在派生類中使用基類時引入不同的行爲。

您的示例調用類的空實現moveMouth()

要調用基類的版本,只是省略了聲明在派生類:

class person : public talk { 
public: 
    int id; 
    person(int a): id(a) { 

    } 

    // Completely omit this if you want to call the base class function by default: 
    // virtual void moveMouth(){ 
     //cout <<"word word word"<<endl; 
    // } 
}; 

要允許去改變,你必須聲明函數作爲基類virtual

class talk{ 

public: 

    int a=5; 
    virtual void moveMouth(){ 
    // ^^^^^^^ 
     cout <<"blah blah blah"<<endl; 
    } 
}; 

繼承層次結構中的多態行爲從您首次引入virtual函數開始。


順便說一句:
多態行爲可以更好地證明這樣

int main(){ 
    talk* t = new person(0); 
    t->moveMouth(); 
    return 0; 
} 
1

那是因爲你必須在你希望它是virtual第一類中聲明的方法爲virtual

另外,virtual當你在類的層次結構中有一個指針或對祖先的引用時,invoke是有意義的。如果你已經有person*那麼你的情況已經是person::talk,沒有其他查找。

2

你需要標記的基類(通話)功能virtual

virtual void moveMouth(){ 
    cout <<"blah blah blah"<<endl; 
} 

覆蓋它在派生類(人):

void moveMouth() override { 
    cout <<"word word word" << endl; 
} 

,取而代之的person* p = new person(0);使用基類指針派生類:

talk* p = new person(0); 

利用多態性be havior。