#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
//基类
class Base1
{
public:
Base1() : x(1) {}
virtual void play() { cout << "Base1::play basketball" << endl; }
virtual void dance() { cout << "Base1::dance dance" << endl; }
private:
int x;
};
//基类
class Base2
{
public:
Base2() : y(2) {}
virtual void print() { cout << "Base2::print hello world" << endl; }
private:
int y;
};
class Base3{
public:
Base3() : z(3) {}
virtual void sing() { cout << "Base3::sing song" << endl; }
private:
int z;
};
//派生类多继承
class Derived : public Base1, public Base2, public Base3{
public:
Derived() : w(4) {}
virtual void play() { cout << "Derived::play basketball" << endl; }
virtual void print() { cout << "Derived::print hello world" << endl; }
virtual void sing() { cout << "Derived::sing song" << endl; }
private:
int w;
};
int main(){
Base1* p1 = new Derived();
Base2* p2 = new Derived();
Base3* p3 = new Derived();
p1->play();
p2->print();
p3->sing();
p1->dance();
return 0;
}
Derived::play basketball // 派生类重写的虚函数,vftable记录的是重写方法的地址
Derived::print hello world // 派生类重写的虚函数,vftable记录的是重写方法的地址
Derived::sing song // 派生类重写的虚函数,vftable记录的是重写方法的地址
Base1::dance dance // 派生类没有重写dance,vftable记录的是基类方法的地址
查看类空间布局:
cl main.cpp /d1reportSingleClassLayoutDerived
派生类对象有三个vfptr,分别对应于三个基类
这些东西在编译阶段就生成指令了,哪个类型的基类指针,访问的就是对应的vfptr,找对应的vftable,取虚函数地址
单继承中,基类有虚函数时,派生类会继承其vfptr,如果派生类有重写虚函数,vftable中就会更新重写方法的地址,如果没有重写虚函数,vftable记录的依然是基类中函数的地址