2017-10-21 44 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。