作用:虚函数的作用就是将接口(函数调用)与实现(函数定义)分开, 就是实现所谓的多态行为。也就是说虚函数提供了让你修改基类函数定义的机会。这里虽然你定义了一个派生类但是这个派生类任然可以按照基类的方式使用,即将派生类对象传递给需要基类引用、指针的函数。
定义: 在一个类中,一个由virtual 关键字修饰的函数声明表示这个函数声明所对应的函数调用既要服务于本类中的函数定义也要服务于派生类中的函数定义,相当于一个接口的作用。
一段良好的代码通常只使用基类提供的接口来编写,那些与派生类相关的代码单独放在一个地方(工厂)。
例子:
class Window {
public:
virtual void drawEvent(void *event); /
virtual void keyEvent(void *event);
virtual void mouseEvent(void *event);
virtual void addWindow(Window *window);
void show();
virtual ~Window(); // 用到继承, 基类的析构函数必须声明为虚函数,否则是逻辑错误
...
};
class Button : public Window {
public:
// 以下声明表示重新定义基类的虚函数的函数体,改变基类相应函数的行为
void drawEvent(void *event);
void keyEvent(void *event);
void mouseEvent(void *event);
void setText(const std::string label);
....
};
class Menu;
class MenuBar : public Window {
public:
// 以下声明表示重新定义基类的虚函数的函数体,改变基类相应函数的行为
void drawEvent(void *event);
void mouseEvent(void *event);
void addWindow(Window *m);
...
};
class Menu : public Window {
public:
// 以下声明表示重新定义基类的虚函数的函数体,改变基类相应函数的行为
void drawEvent(void *event);
void mouseEvent(void *event);
void keyEvent(void *event);
};
void userCode(Window &win, Window &win2) {
win.addWindow(win2); //用户代码只用到了基类的引用
}
int main() {
Window mainWindow(...);
MenuBar menuar(...);
Menu fileMenu(...);
Button button(...);
usrCode(mainWindow, menuBar); //将MenuBar对象当做Window引用来使用,由于定义了虚函数,所以usrCode会使用我们重定义的代码
usrCode(menuBar, fileMenu); //...
usrCode(mainWindow, button); //...
mainWindow.show();
}
虚函数的定义及作用:简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略
举例:class A
{
public:
void print(){ cout<<”This is A”<
class B:public
{
public:
void print(){ cout<<”This is B”<
int main() //为了在以后便于区分,我这段main()代码叫做main1
{
A a;
B b;
a.print();
b.print();
}
通过class A和class B的print()这个接口,可以看出这两个class因个体的差异而采用了不同的策略,输出的结果也是我们预料中的,分别是This is A和This is B。但这是否真正做到了
呢?No,多态还有个关键之处就是一切用指向
的指针或引用来操作对象。那现在就把main()处的代码改一改。
int main(){ //main2
A a;
B b;
A* p1=&a;
A* p2=&b;
p1->print();
p2->print();
}
运行一下看看结果,哟呵,
,结果却是两个This is A。问题来了,p2明明指向的是class B的对象但却是调用的class A的print()函数,这不是我们所期望的结果,那么解决这个问题就需要用到虚函数
class A{
public:
virtual void print(){ cout<<”This is A”<
};
class B:public A
{
public:
void print(){ cout<<”This is B”<
毫无疑问,class A的成员函数print()已经成了虚函数,那么class B的print()成了虚函数了吗?回答是Yes,我们只需在把
的成员函数设为virtual,其
的相应的函数也会自动变为虚函数。所以,class B的print()也成了虚函数。那么对于在
的相应函数前是否需要用virtual关键字修饰,那就是你自己的问题了。
现在重新运行main2的代码,这样输出的结果就是This is A和This is B了。
现在来消化一下,我作个简单的总结,指向
的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
如楼上各位所说, 虚函数就是为了让代码的耦合度降低, 可以将接口和实现分离, 这个好处是很多的, 能够解决面向过程编程的很多问题, 基本上就是面向对象的核心,