关于C++虚函数,主要是服务于多态,但里面一些细节的点还是很多的,我总结一下我目前所遇到的基本重要的几点,通过一下几个方面讲解:
- 虚函数的介绍
- 那些函数可以设为虚函数?那些函数不行?
- 纯虚函数
虚函数的介绍:
虚函数说白了就是成员函数前加上virtual,虚函数主要实现多态,对多态访问父类函数方法进行操作。但是在这里有一个细节性的问题:虚函数是如何实现子类访问父类的函数的呢?
这里我们要知道一个叫虚函数表的概念,当我们书写一个类,给类的成员函数加上virtual后,这个类的大小就会相比较没有加virtual时,多了四个字节。
例子:
class Base
{
public:
virtual void func();
private:
int ma;
int mb;
};
大家可以在VS的代码源目录文件中,键入命令:/d1reportSingleClassLayout查看想要查看的类:
可以看到,多了一个叫vfptr的指针,占四个字节,而这个指针就是指向虚函数表,所谓虚函数表,就是存放了你设计的虚函数的地址,这也就能解释了,为什么子类可以访问父类的函数,就是通过虚函数指针,访问了虚函数表中函数。
这里要注意一点:如果子类也定义了一个虚函数并且与父类的同名,那么虚函数表中的函数就会把父类的虚函数地址替换成子类的。
关于虚函数表:虚函数表是在编译阶段生成的,父类有父类的vfptr指向的虚函数表,子类有子类的,当虚函数表生成后,存放在内存的.rodata段,也就是只读数据段,只可以读取,不可以修改。
那些函数可以成为虚函数?那些函数又不能呢?
能否成为虚函数的判定方法只有两点:
- 能够产生函数符号地址;
- 必须依赖于对象;(只能通过对象的前四个字节 vfptr 才能访问虚函数表,进而访问虚函数的地址,)
基于以上两点,可以分析出能够成为虚函数的有:
- 析构函数
- 普通成员函数
而不能成为虚函数的有:
- 构造函数:构造函数在调用时,还没有产生对象;
- 带静态关键字static的函数:静态成员函数是类的组成部分,不是对象的,所有对象共享一份,没必要设为虚函数,静态成员函数有没办法继承;
- 内联函数:由于内联函数在编译时期被展开,变成了代码块,提高了编译运行效率,但是虚函数的动态绑定是在运行时间完成的,所以没法设成虚函数;
- 友元函数:友元函数不是类的成员函数,不支持继承友元函数,更不能设为虚函数了
- 普通函数:这个就很好理解了,都不在类里面,更别提继承绑定什么的了
纯虚函数
知道了虚函数,理解纯虚函数就不难了,虚函数中总有一些特例情况,在基类中会有一些成员方法没法实现,只能设成纯虚函数,再交给继承类具体实现功能。
比如如下代码:
class CMan
{
public:
virtual void talk() = 0;
};
设计一个类:人,这个人的动作是talk,说,但是说话这方法怎么具体实现呢,只能通过子类具体实现相关的内容,这就是纯虚函数。
关于虚函数的内容我大概就总结了这么多,大致上把虚函数的内容总完了,还有就是根据虚函数的扩展知识,动态绑定之类的,呢些就要和静态绑定和继承派生结合着说了,后面再做总结。
来源:CSDN
作者:AIxiaoming1105
链接:https://blog.csdn.net/AIxiaoming1105/article/details/104345085