C++中的虚函数

之前被某公司面试官问过一次虚函数是什么。至今印象深刻,因为当时并没有回答上来。于是趁今天有空,把虚函数翻了翻,发个blog总结一下。


虚函数的作用

虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数

——引自经典教材谭老师的红皮书

那么,虚函数就是解决类的继承过程中同名函数的处理问题,详细点说就是处理不同派生层次上的同名函数问题。举栗子来说,对于一个基类Student和其子类Graduate,都有一个同名函数display() (陈列出实例的详细信息)。对于学生这个类而言,属性有(学号,姓名,分数)这3个,对于毕业生而言,属性除这3个以外还有一个工资。所以,这两个类的同名函数display()具有不一样的功能,前者访问3个属性并打印出来,后者访问4个属性并打印出来。那么怎么使这两个同名函数不冲突呢?其实也好办,不使用虚函数也好办,我们只需定义不同的实例名然后通
过实例名调用函数就可以了。打比方,
Student s1(x,x,x);
Graduate g1(x,x,x,x);
s1.display();
g1.display();
这样就可以使两个同名函数不冲突,这就有点像JAVA编程风格了,同名函数一律按覆盖处理。看起来没有问题,也很方便的样子。 其实,对于复杂的情况下,这种做法是相当不方便的。举个栗子,当一个基类派生出各种不同的子类,每个子类都有这么一个同名函数,你现在去调用这个各个子类中的同名函数,然后手敲各个实例名来调用?对于复杂的调用,C++还是得靠指针,这样也更高大上一些。
直接来看一个代码实例:(来自谭老师的红皮书)

#include<iostream>
#include<string>
using namespace std;
class Student {
public:
 Student(int, string, float);
 void display();
protected:
 int num;
 string name;
 float score;
};

Student::Student(int n, string nam, float s) {
 num = n;
 name = nam;
 score = s;
}

void Student::display() {
 cout << "num:" << num << "\nname:" << name << "\nscore:" << score << "\n\n";
}

class Graduate :public Student {
public:
 Graduate(int, string, float, float);
 void display();
private:
 float pay;
};

void Graduate::display() {
 cout << "num:" << num << "\nname:" << name << "\nscore:" << score << "\npay = " << pay << endl;
}

Graduate::Graduate(int n, string nam, float s, float p):Student(n,nam,s),pay(p){}

int main() {
 Student stud1(1001, "Li", 87.5);
 Graduate grad1(2001, "Wang", 98.5, 563.5);
 Student *pt = &stud1;
 pt->display();
 pt = &grad1;
 pt->display();
 grad1.display();
 system("pause");
 return 0;
}

输出:
在这里插入图片描述
如上述代码所示,我用基类指针pt指向基类实例stud1,再通过pt调用stud1的display函数,是完全没有问题的。但是,如果用基类指针指向子类实例grad1,再调用其display函数,发现陈列的仍然基类的信息,并没有访问grad1的第4个信息pay。我们可以看到,如果用Graduate的某个实例名grad1调用display函数,可以完全实现新的display。当然,我们想要的并不是通过实例名调用,而是通过基类指针调用。那么,就需要我们的虚函数了。
如下:将基类中的display函数前面加一个virtual就可以了

virtual void display();

再看一下输出结果:

在这里插入图片描述
关键是第二段输出,基类指针访问子类实例中的同名函数,能够实现子类函数的功能。这就是虚函数的作用之所在!


总结

当把基类的某个成员函数声明为虚函数后,允许在其派生类中对该函数重新定义,赋予它新的功能,并且可以通过指向基类的指针指向同一类族中不同类的对象,从而调用其中的同名函数。由虚函数实现的动态多态性就是:同一类族中不同类的对象对同一函数调用做出不同的响应

猜你喜欢

转载自blog.csdn.net/leviopku/article/details/83004563