多重继承虚函数表分析

多重继承虚函数表分析

演示在多重继承下,虚函数表的样子

创建两个父类Base1 Base2,并创建Derived先后继承Base1 Base2 ,查看对于各个函数的调用结果

#include <iostream>
using namespace std;

class Base1
{
public:
	virtual void f() {
		cout << "Base1::f()" << endl;
	}

	virtual void g() {
		cout << "Base1::g()" << endl;
	}
};

class Base2
{
public:
	virtual void h() {
		cout << "Base2::h()" << endl;
	}

	virtual void i() {
		cout << "Base2::i()" << endl;
	}
};

class Derived : public Base1, public Base2
{
public:
	virtual void f() {
		cout << "Derived::f()" << endl; // 只覆盖Base1的f
	}

	virtual void i() {
		cout << "Derived::i()" << endl; // 只覆盖Base2的i
	}

	// 如下三个是本类自己的虚函数
	virtual void mh() {
		cout << "Derived::mh()" << endl;
	}

	virtual void mi() {
		cout << "Derived::mi()" << endl;
	}

	virtual void mj() {
		cout << "Derived::mj()" << endl;
	}
};

int main()
{
	typedef void(*Func)(void); // 定义了一个函数指针,typedef就代表Func是一个函数指针类型,可以将它当作类型使用
	
	cout << "sizeof(Base1)" << " = " << sizeof(Base1) << endl;
	cout << "sizeof(Base2)" << " = " << sizeof(Base2) << endl;
	cout << "sizeof(Derived)" << " = " << sizeof(Derived) << endl;
	cout << "子类的大小有8且无成员变量,说明有两个虚函数指针" << endl;

	
	Derived ins;		// 子类对象
	Base1& b1 = ins;	// 父类指针指向子类
	Base2& b2 = ins;	// 父类指针指向子类
	Derived& d = ins;	// 子类指针指向子类

	// 第一个虚函数指针(子类的)
	long* pderived1 = (long*)(&ins);
	long* vptr1 = (long*)(*pderived1);

	// 第二个虚函数指针(子类的)
	long* pderived2 = pderived1 + 1;
	long* vptr2 = (long*)(*pderived2);
	
	// 先从第一个继承的父类里找函数,如果覆盖的,就弄成自己的,如果自己没覆盖,就弄成父亲的
	// 子类分别覆盖了 f, i
	Func f1 = (Func)vptr1[0];	// Derived::f()
	Func f2 = (Func)vptr1[1];	// Base1::g()
	Func f3 = (Func)vptr1[2];	// Derived::mh()
	Func f4 = (Func)vptr1[3];	// Derived::mi()
	Func f5 = (Func)vptr1[4];	// Derived::mj()
	Func f6 = (Func)vptr1[5];
	Func f7 = (Func)vptr1[6];
	Func f8 = (Func)vptr1[7];

	// 这里找另一个父类
	Func f11 = (Func)vptr2[0];	// Base2::h
	Func f22 = (Func)vptr2[1];	// Derived::i()
	Func f33 = (Func)vptr2[2];	
	Func f44 = (Func)vptr2[3];	
	Func f55 = (Func)vptr2[4];

	cout << "-------------------" << endl;
	cout << "父类指针指向子类,调用函数得到的都是子类的虚函数" << endl;
	b1.f();	// Derived::f()
	b2.i();	// Derived::i()	
	d.f();	// Derived::f()
	d.i();	// Derived::i()
	d.mh();	// Derived::mh()
	
	cout << "-------------------" << endl;
	cout << "打印子类第一个虚函数表,对应Base1,子类覆盖了Base::f()" << endl;
	f1();
	f2();
	f3();
	f4();
	f5();
	//f6(); 无法访问

	cout << "-------------------" << endl;
	cout << "打印子类第二个虚函数表,对应Base2,子类覆盖了Base::i()" << endl;
	cout << "并且第二个虚函数表里面无法访问子类自己的虚函数,说明子类的虚函数都在第一个虚函数表" << endl;
	f11();
	f22();
	//f33(); 无法访问
	//f44(); 无法访问
	//f55(); 无法访问
	cout << "-------------------" << endl;

	return 0;
}
sizeof(Base1) = 4
sizeof(Base2) = 4
sizeof(Derived) = 8
子类的大小有8且无成员变量,说明有两个虚函数指针
-------------------
父类指针指向子类,调用函数得到的都是子类的虚函数
Derived::f()
Derived::i()
Derived::f()
Derived::i()
Derived::mh()
-------------------
打印子类第一个虚函数表,对应Base1,子类覆盖了Base::f()
Derived::f()
Base1::g()
Derived::mh()
Derived::mi()
Derived::mj()
-------------------
打印子类第二个虚函数表,对应Base2,子类覆盖了Base::i()
并且第二个虚函数表里面无法访问子类自己的虚函数,说明子类的虚函数都在第一个虚函数表
Base2::h()
Derived::i()
-------------------
  • 一个对象,如果它所属的类有多个基类,则有多个虚函数表指针(是虚函数表指针而不是有多个虚函数表)

  • 在多重继承中,对应各个记类的vptr按继承顺序依次放置在类内存空间中,且子类与基类共用同一个vptr

    比如本例子,第一个vptr指向的虚函数表里含有子类的虚函数,而第二个vptr的虚函数表并无

虚函数表图片

image-20211203111747442

  • 子类对象ins有两个虚函数表指针,vptr1 vptr2
  • Derived有两个虚函数表,因为它继承自两个基类
  • 子类和第一个基类共用一个vptr,也可以说共用一个虚函数表
  • 子类中的虚函数覆盖了父类中的同名虚函数
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值