虚函数
在函数定义时前面添加一个virtual修饰,所产生的函数就是虚函数。
虚函数是为了实现多态,重定向对象行为的函数,通俗理解就是父类自己不怎么干活,而让孩子们干活,但是当孩子没有办法干活的时候父亲也会替孩子干活的。
有很多时候孩子们确实是想有一些具体的行为属性。比如对于“人类”这个类来说,它是可以设置资产,而可以具体到子类中哪个人的资产上,所以这个时候“人类”这个类可以定义抽象的行为virtual(默认每个人最初的资产为0),让子类继承并去实现具体行为。
在代码中表示为:
#include <iostream>
using namespace std;
class people
{
int salary = 0;
public:
virtual void getSalary() //虚函数
{
cout << this->salary << endl;
}
};
class employee : public people
{
int salary=1000;
public:
void getSalary() override//override 确保基类函数被覆盖
{
cout << this->salary << endl;
}
};
class employer : public people
{
//int salary=0;
public:
void getsomething()
{
printf("instance employer\n");
}
};
people *p1 = new employee();
p1->getSalary();
people *p2 = new employer();
p2->getSalary();
结果:
1000
0
而如果为了保证派生类会覆盖到基类的虚函数,则可以在要覆盖的函数后写上override,这样如果不小心拼写错误无法覆盖基类,则会报错。
纯虚函数
- 定义纯虚函数的类无法new对象。
- 定义纯虚函数的类是接口类,必须有继承子类才能使用。
定义纯虚函数的类不能用于生成对象,纯虚函数的类被认为是接口类,无法直接产生对象。
#include <iostream>
using namespace std;
class people
{
public:
virtual void getSalary()=0;
};
class employee: public people
{
public:
void getSalary() override
{
cout << this->salary <<endl;
}
};
class employer: public people
{
int salary = 2000;
public:
void getsomthing()
{
cout << "get somthing"<<endl;
}
};
people *p1 = new employer();
p1->getSalary();
如以上的代码中在编译时会报错的,因为employer类中没有对纯虚函数getSalary进行覆盖,所以纯虚函数是强迫派生类必须自己定义函数行为,这个要比虚函数更强硬。
父亲强迫孩子必须什么事情都自己干,不能指望父亲给你做,因为父亲不会做事情,这个父亲的形象有点像神,因为你不可能希望神去为你做事情,而是神指派你做事情,好吧,扯远了,我是无神论者,哈哈。
必须在employer中添加上getSalary函数才能正常编译。
class employer: public people
{
int salary=2000;
pulbic: void getSalary(){cout<<this->salary<<endl;}
//...
};
people * p1 = new employer();
p1->getSalary();
总结
虚函数和纯虚函数:相同点都是为了得到多态行为,都是进行派生和继承;不同点是虚函数可以写自己的函数体,可以创建对象,不强制子类覆盖该函数,而纯虚函数不能实现函数体,不能创建对象,子类必须覆盖该函数。
* 而虚基类的概念,在我前一个文章中已经提到了,不同于虚函数和纯虚函数。