如果有虚函数 创建对象时 编译器会创建虚表指针 指向本类的虚函数表
当基类指针指向子类对象时,调用虚函数时会通过虚表指针进入本类的虚函数表找到函数。找到函数后,编译器将函数名替换为相应地址。
这就是多态的本质
虚表指针占4字节 放置在对象的前4字节
普通函数--编译器直接替换为函数地址
虚函数-编译器查询地址中的虚函数表后,替换为相应的函数地址
#include <iostream>
#include <cstring>
using namespace std;
class A //double 8字节
{
double d;
};
class B:public A //两个double类型 16字节 普通函数放在代码区 不占对象大小
{
double d;
public:
void f(){}
};
//只要有虚函数 就要多出一个虚函数指针的4字节
class C //double 8字节 + 虚函数指针4字节 = 12字节
{
double d;
public:
virtual void f(){cout << "this = "<< this << ",C类虚函数,&d = " << &d<<endl;}
virtual void g() {cout << "C类虚函数 g"<<endl;}
virtual void h(){}
virtual void i(){}
virtual void j(){}
};
class D:public C //两个double 16字节+ 虚函数指针4字节 = 20字节
{
double d;
public:
virtual void f(){cout << "D类虚函数" <<endl;}
};
int main()
{
cout << sizeof(A) <<endl; //8
cout << sizeof(B) <<endl; //16
cout << sizeof(C) <<endl;//12
cout << sizeof(D) <<endl;//20
A *p = new B;
C *q1 =new C,*q2 = new D;
q1->f();//C类虚函数 this = 0x984b020,C类虚函数,&d = 0x984b024
//由此可以看到0x984b020也即对象前4字节存放的是虚表指针。
q2->f(); //D类虚函数
cout << "------------------------------------" <<endl;
memcpy(q2,q1,4); //将q1的前4字节 考向q2的前四字节 也就是将q2的虚表指针指向了q1的虚表
q2->f(); //this = 0x87c9030,C类虚函数,&d = 0x87c9034 q2调用了q1的虚函数
delete p;
delete q1;
delete q2;
}