多态调用的原理

问题:为什么派生类对基类的虚函数重写,通过基类对象的指针或引用>调用该虚函数,就可以实现多态
因为有序函数的类的对象模型的前四个字节存储的是一个地址,这个地址指向的是一个虚拟函数表,表中的内容是虚拟函数的地址。

在这里插入图片描述


#include <iostream>
#include <string>
using namespace std;

typedef void(*PVFT)();     //定义一个函数指针

class Base
{
public:
	virtual void TestFun1()
	{
		cout << "Base::TestFunc1()"<<endl;
	}


	virtual void TestFun2()
	{
		cout << "Base::TestFunc2()" << endl;
	}

	virtual void TestFunc3()
	{
		cout << "Base::TestFunc3()" << endl;
	}

	int _b;
};

void printVTF(Base& b,const string& desc)
{
	//(&b)  //取类b的地址(指针)
	//(int*)(&b)  //因为需要前四个字节的内容,所以对其强转为(int*)
	//*(int*)(&b)  //将前四个字节的内容取到
	//(PVFT*)*(int*)(&b)  //将前四个字节的内容取到作为地址
	//赋值给函数指针
	cout <<desc<< endl;
	PVFT* PV = (PVFT*)*(int*)(&b);
	while (*PV)
	{
		(*PV)();
		++PV;
	}
	
}

int main()
{
	cout << sizeof(Base) << endl;

	Base b;
	b._b = 10;

	printVTF(b,"Base");
	system("pause");
	return 0;
}
普通函数:直接调用
虚函数的调用(满足多态条件)
  1. 从对象前4个字节中取虚表的地址
  2. 传递this指针
  3. 从虚表中获取虚函数的地址(在虚表地址+虚函数在虚表中的偏移量)
  4. 调用虚函数

单继承

  1. 基类有虚函数,继承基类,派生类将基类的虚表拷贝到自己的虚表中
  2. 派生类某个虚函数如果重写基类的虚函数,替代相同偏移量位置的虚函数为子类的虚函数
  3. 如果派生类新增加自己特有的虚函数,将其放在基类继承下来虚函数的后面。
#include <iostream>
#include <string>
using namespace std;

typedef void(*PVFT)();

class Base
{
public:
	virtual void TestFun1()
	{
		cout << "Base::TestFunc1()" << endl;
	}


	virtual void TestFun2()
	{
		cout << "Base::TestFunc2()" << endl;
	}

	virtual void TestFunc3()
	{
		cout << "Base::TestFunc3()" << endl;
	}

	int _b;
};

void printVTF(Base& b, const string& desc)
{
	//(&b)  //取类b的地址(指针)
	//(int*)(&b)  //因为需要前四个字节的内容,所以对其强转为(int*)
	//*(int*)(&b)  //将前四个字节的内容取到
	//(PVFT*)*(int*)(&b)  //将前四个字节的内容取到作为地址
	//赋值给函数指针
	cout << desc << endl;
	PVFT* PV = (PVFT*)*(int*)(&b);
	while (*PV)
	{
		(*PV)();
		++PV;
	}

}

class Derived : public Base
{
public:
	virtual void TestFun2()
	{
		cout << "Derived::TestFunc2()" << endl;
	}

	virtual void TestFunc3()
	{
		cout << "Derived::TestFunc3()" << endl;
	}
	int _d;
};

int main()
{
	cout << sizeof(Base) << endl;
	cout << sizeof(Derived) << endl;

	Derived d;
	d._b = 1;
	d._d = 2;

	printVTF(d, "Deived VIF:");
	system("pause");
	return 0;
}

带有虚函数的多继承对象的模型以及虚表

  1. 多继承,将派生类自己的新增加的虚函数添加到第一张虚表最后
#include <iostream>
#include <string>
using namespace std;

class B1
{
public:
	virtual void TestFunc1()
	{
		cout << "B1::TestFunc1" << endl;
	}

	virtual void TestFunc2()
	{
		cout << "B1::TestFunc2" << endl;
	}

	int _b1;
};

class B2
{
public:
	virtual void TestFunc3()
	{
		cout << "B2::TestFunc3" << endl;
	}

	virtual void TestFunc4()
	{
		cout << "B2::TestFunc4" << endl;
	}
	int _b2;
};


class D:public B1, public B2
{
public:
	virtual void TestFunc1()
	{
		cout << "D::TestFunc1" << endl;
	}

	virtual void TestFunc4()
	{
		cout << "D::TestFunc4" << endl;
	}

	virtual void TestFunc5()
	{
		cout << "D::TestFunc5" << endl;
	}
	int _d;
};

typedef void(*PVTF)();
void PrintVTF(B1& b,const string& str)    //不能传值(不是外面的实体),必须指针或引用,
{
	PVTF* PV = (PVTF*)(*(int*)&b);
	cout << str << endl;
	while (*PV)
	{
		(*PV)();
		++PV;
	}
}

void PrintVTF(B2& b, const string& str)    //不能传值(不是外面的实体),必须指针或引用,
{
	PVTF* PV = (PVTF*)(*(int*)&b);
	cout << str << endl;
	while (*PV)
	{
		(*PV)();
		++PV;
	}
}


int main()
{
	cout << sizeof(D) << endl;
	D d;
	d._b1 = 1;
	d._b2 = 2;
	d._d = 3;

	B1& b1 = d;
	PrintVTF(b1,"D VTF of B1");

	B2& b2 = d;
	PrintVTF(b2, "D VTF of B2");


	system("pause");
	return 0;
}

在这里插入图片描述
上面代码的输出结果
在这里插入图片描述

带有虚函数的菱形继承

#include <iostream>
#include <string>
using namespace std;

class B
{
public:
	virtual void TestFunc1()
	{
		cout << "B::TestFunc1()" << endl;
	}

	virtual void TestFunc2()
	{
		cout << "B::TestFunc2()" << endl;
	}
	int _b;
};

class C1 : public B
{
public:
	virtual void TestFunc1()
	{
		cout << "C1::TestFunc1()" << endl;
	}

	virtual void TestFunc3()
	{
		cout << "C1::TestFunc3()" << endl;
	}

	int _c1;
};

class C2 : public B
{
public:
	virtual void TestFunc2()
	{
		cout << "C2::TestFunc2()" << endl;
	}

	virtual void TestFunc4()
	{
		cout << "C2::TestFunc4()" << endl;
	}
	int _c2;
};


class D : public C1, public C2
{
public:
	virtual void TestFunc3()
	{
		cout << "D::TestFunc3()" << endl;
	}

	virtual void TestFunc4()
	{
		cout << "D::TestFunc4()" << endl;
	}

	virtual void TestFunc5()
	{
		cout << "D::TestFunc5()" << endl;
	}

	int _d;
};

typedef void(*PVTF)();
void PrintVTF(C1& b, const string& str)    //不能传值(不是外面的实体),必须指针或引用,
{
	PVTF* PV = (PVTF*)(*(int*)&b);
	cout << str << endl;
	while (*PV)
	{
		(*PV)();
		++PV;
	}
}

void PrintVTF(C2& b, const string& str)    //不能传值(不是外面的实体),必须指针或引用,
{
	PVTF* PV = (PVTF*)(*(int*)&b);
	cout << str << endl;
	while (*PV)
	{
		(*PV)();
		++PV;
	}
}

int main()
{
	cout << sizeof(D) << endl;

	D d;
	d.C1::_b = 0;
	d._c1 = 1;

	d.C2::_b = 2;
	d._c2 = 3;
	d._d = 4;

	C1& c1 = d;
	PrintVTF(c1,"D VTF of c1");

	C2& c2 = d;
	PrintVTF(c2, "D VTF of c2");

	system("pause");
	return 0;
}

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值