多态调用的原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wan_shibugong/article/details/82763822

问题:为什么派生类对基类的虚函数重写,通过基类对象的指针或引用>调用该虚函数,就可以实现多态

因为有序函数的类的对象模型的前四个字节存储的是一个地址,这个地址指向的是一个虚拟函数表,表中的内容是虚拟函数的地址。

在这里插入图片描述


#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;
}

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Wan_shibugong/article/details/82763822