虚函数(Virtual)
在结构体封装的函数前面加上Virtual
class Base
{
public:
void Function_1()
{
printf("Function_1...\n");
}
virtual void Function_2()
{
printf("Function_2...\n");
}
};
注:通过对象调用虚函数时,虚函数与普通函数都是E8 Call(直接call)。通过指针调用时虚函数是FF Call(间接call)
虚函数地址表
当在类中的成员有虚函数时,类的大小会多四个字节(无论有多少个虚函数,只多四字节)。
作业一(单继承无函数覆盖)
#include<stdio.h>
struct Base
{
public:
virtual void Function_1()
{
printf("Base:Function_1...\n");
}
virtual void Function_2()
{
printf("Base:Function_2...\n");
}
virtual void Function_3()
{
printf("Base:Function_3...\n");
}
};
struct Sub :Base
{
public:
virtual void Function_4()
{
printf("Sub:Function_4...\n");
}
virtual void Function_5()
{
printf("Sub:Function_5...\n");
}
virtual void Function_6()
{
printf("Sub:Function_6...\n");
}
};
void TestMethod()
{
//查看 Sub 的虚函数表
Sub base;
//对象的前四个字节就是虚函数表
printf("base 的虚函数表地址为:%x\n", *(int*)&base);
//通过函数指针调用函数,验证正确性
typedef void(*pFunction)(void);
pFunction pFn;
for (int i = 0; i < 6; i++)
{
int temp = *((int*)(*(int*)&base) + i);
pFn = (pFunction)temp;
pFn();
}
}
int main() {
TestMethod();
return 0;
}
作业二(单继承,有覆盖)
#include<stdio.h>
struct Base
{
public:
virtual void Function_1()
{
printf("Base:Function_1...\n");
}
virtual void Function_2()
{
printf("Base:Function_2...\n");
}
virtual void Function_3()
{
printf("Base:Function_3...\n");
}
};
struct Sub :Base
{
public:
virtual void Function_1()
{
printf("Sub:Function_1...\n");
}
virtual void Function_2()
{
printf("Sub:Function_2...\n");
}
virtual void Function_6()
{
printf("Sub:Function_6...\n");
}
};
void TestMethod()
{
//查看 Sub 的虚函数表
Sub base;
//对象的前四个字节就是虚函数表
printf("base 的虚函数表地址为:%x\n", *(int*)&base);
//通过函数指针调用函数,验证正确性
typedef void(*pFunction)(void);
pFunction pFn;
for (int i = 0; i < 4; i++)
{
int temp = *((int*)(*(int*)&base) + i);
pFn = (pFunction)temp;
pFn();
}
}
int main() {
TestMethod();
return 0;
}
总结:子类会继承父类虚函数。子类和父类虚函数重复,颠覆继承、