1. 纯虚函数
1)概念
在虚函数的声明结尾处添加“=0”,这种虚函数被称为纯虚函数,是一个没有实现只有声明的函数
2)作用
为了让类具有抽象类的功能,让继承自抽象类的子类都具有虚表以及虚表指针
3)纯虚函数在虚表中的处理
因为纯虚函数没有实现代码,所以没有首地址。编译器为了防止误调用纯虚函数,将虚表中保存的纯虚函数的首地址项替换成函数__purecall,用于结束程序
2. 抽象类
不能实例化(且不可作为参数、返回值、类型转换)(声明抽象类指针或引用,指向子类来体现多态)
1)概念
含有纯虚函数的类
2)抽象类的特征
一旦在虚表中发现函数地址为__purecall(GCC编译器函数名称为___cxa_pure_virtual)函数的地址时,可以高度怀疑此虚表对应的类是一个抽象类
当抽象类中定义了多个纯虚函数时,虚表中将保存相同的函数指针
c++代码示例:
#include <stdio.h>
class AbstractBase {
public:
AbstractBase() {
printf("AbstractBase()");
}
virtual void show() = 0; //定义纯虚函数
};
class VirtualChild : public AbstractBase { //定义继承抽象类的子类
public:
virtual void show() { //实现纯虚函数
printf("抽象类分析\n");
}
};
int main(int argc, char* argv[]) {
VirtualChild obj;
obj.show();
return 0;
}
vs_x86汇编标识:
00401020 push ebp ;抽象类构造函数
00401021 mov ebp, esp
00401023 push ecx
00401024 mov [ebp-4], ecx
00401027 mov eax, [ebp-4]
0040102A mov dword ptr [eax], offset ??_7AbstractBase@@6B@ ;设置抽象类虚表指针
00401030 push offset aAbstractbase ; "AbstractBase()"
00401035 call sub_4010D0 ;调用printf函数
0040103A add esp, 4
0040103D mov eax, [ebp-4]
00401040 mov esp, ebp
00401042 pop ebp
00401043 retn
;抽象类AbstractBase中虚表信息的第一项所指向的函数首地址
0000:00401C3B push esi ;__purecall函数
0000:00401C3C mov esi, dword_419C6C
0000:00401C42 test esi, esi
0000:00401C44 jz short loc_401C50
0000:00401C46 mov ecx, esi
0000:00401C48 call ds:___guard_check_icall_fptr
0000:00401C4E call esi ; dword_419C6C
0000:00401C50 call _abort ;结束程序
标签:0000,函数,mov,纯虚,虚表,抽象类
From: https://www.cnblogs.com/XiuzhuKirakira/p/17157425.html