浅谈c++虚函数 虚继承的虚表剖析

 1 虚函数的虚表剖析

  (1)没有覆盖公有继承 派生类的虚表

class CBase //没有覆盖
{
public:
	virtual void FunTest0(){ cout << "CBase::FunTest0()"; }
	virtual void FunTest1(){ cout << "CBase::FunTest1()"; }
	virtual void FunTest2(){ cout << "CBase::FunTest2()"; }
public:
	int data1;
};
class CDerived :public CBase
{
public:
	virtual void FunTest4(){ cout << "CDerived::FunTest4()"; }
	virtual void FunTest5(){ cout << "CDerived::FunTest5()"; }
	virtual void FunTest6(){ cout << "CDerived::FunTest6()"; }
	int data2;
};

typedef void(*FUN_TEST)(); //定义一个函数指针
void PrintVF()
{
	// 1种方法
	//for (int idx = 0; idx < 3;idx++)
	//{
	//	FUN_TEST funTest = (FUN_TEST)(*((int*)*(int *)&b + idx));
	//	// (int *)&b将b的地址值强转换成int*指针
	//	//*(int *)&b 将b的地址值取出来 0021fe04
	//	//(int*)*(int *)&b 将0021fe04 强转换成一个指针   +idx 指针里面的东西偏移idx单元
	//	//*((int*)*(int *)&b 将0021fe04 地址里面的值取出来
	//	funTest();
	//	cout << ": " << (int *)funTest << endl;
	//}
	CDerived d;
	d.data2 = 2;
	d.data1 = 1;
	cout << "CDerived的大小:" << sizeof(CDerived) << endl;
	cout << "CDerived vfptr:" << endl;
	FUN_TEST *funTest2 = (FUN_TEST*)(*(int*)&d);
	while (*funTest2)
	{
		(*funTest2)();
		cout << ": " << *funTest2 << endl;
		funTest2++;
	}
}
  剖析 虚表

   浅谈c++虚函数 虚继承的虚表剖析_第1张图片

  说明:虚函数按声明顺序存在于虚表中;

             在派生类中,前面是基类的虚函数,后面是派生类的虚函数

(2)有覆盖 的公有继承派生类的虚表

   

class CBase
{
public:
	CBase()
		:data1(1)
	{}
	virtual void FunTest0(){ cout << "CBase::FunTest0()" ; }
	virtual void FunTest1(){ cout << "CBase::FunTest1()" ; }
	virtual void FunTest2(){ cout << "CBase::FunTest2()" ; }
	virtual void FunTest3(){ cout << "CBase::FunTest3()" ; }
	int data1;
};
class CDerived :public CBase
{
public:
	CDerived()
		:data2(2)
	{}
	virtual void FunTest0(){ cout << "CDerived::FunTest0()" ; } //重写
	virtual void FunTest1(){ cout << "CDerived::FunTest1()" ; }//重写
	virtual void FunTest4(){ cout << "CDerived::FunTest4()" ; }
	virtual void FunTest5(){ cout << "CDerived::FunTest5()" ; }
	int data2;
};

typedef void(*_pFunTest)();
void PrintVF() //打印虚表
{
	CDerived derived;
	derived.data1 = 1;
	derived.data2 = 2;
	cout << "CDerived vfptr:" << endl;
	_pFunTest* pFunTest2 = (_pFunTest*)(*(int *)&derived);
	while (*pFunTest2)
	{
		(*pFunTest2)();
		cout << ": " << *pFunTest2 << endl;
		pFunTest2++;
	}
}
void TestVirtual() // 测试调用基类还是派生类的虚表
{
	CBase base;
	CDerived derived;
	CBase* PBase1 = &base; // 基类的指针指向基类,获取到的是基类的虚表
	PBase1->FunTest0(); //调用基类的FunTest0
	cout << endl;
	CBase* PBase2 = &derived;//基类的指针指向派生类,获取到的是派生类的虚表
	PBase2->FunTest0();  //掉用派生类FunTest0

}
 虚表剖析

 浅谈c++虚函数 虚继承的虚表剖析_第2张图片浅谈c++虚函数 虚继承的虚表剖析_第3张图片

    派生类虚表的形成: a.先拷贝基类的虚表 

     b.如果派生类重写了基类的虚函数,则修改同位置的基类虚函数

     c.跟上派生类新定义的虚函数

   调用虚表:通过基类的引用或指针调用虚函数时,调用基类还是派生类的虚函数,

     要根据运行时引用或指针的实际指向的类型确定。

    单继承的派生类的大小:虚表+ 基类的数据成员 + 派生类的成员

  2 多继承

  

class Base1  //有覆盖
{
public:
	Base1()
	:_data1(1)
	{}
	virtual void Test1()
	{
		cout << "Base::Test1()";
	}
	virtual void Test2()
	{
		cout << "Base::Test2()";
	}
	virtual void Test3()
	{
		cout << "Base::Test3()";
	}
	int _data1;
};
class Base2
{
public:
	Base2()
		:_data2(2)
	{}

	virtual void Test4()
	{

		cout << "Base::Test4()" ;
	}
	virtual void Test5()
	{
		cout << "Base::Test5()" ;
	}
	virtual void Test6()
	{
		cout << "Base::Test6()" ;
	}
	int _data2;

};
class Derived :public Base1, public Base2
{
public:
	Derived()
		:_data3(3)
	{}
	virtual void Test1()
	{
		cout << "Derived::Test1()" ;
	}
	virtual void Test5()
	{
		cout << "Derived::Test5()" ;
	}
	virtual void Test7()  //添加到Base1的虚表中
	{
		cout << "Derived::Test7()" ;
	}
	int _data3;
};
typedef void(*VFP)();
void PrintVfp()
{
	Derived d;
	d._data1 = 1;
	d._data2 = 2;
	d._data3 = 3;
	VFP* vfp = (VFP*)*(int *)&d;
	cout << "Derived vir table:" << endl;
	while (*vfp)
	{
		(*vfp)();
		cout <<": "<< *vfp << endl;
		++vfp;
	}
	cout << endl;

	Base1& b1 = d;
	VFP* vfp1 = (VFP*)*(int *)&b1;
	cout << "Base1 vir table:" << endl;
	while (*vfp1)
	{
		(*vfp1)();
		cout << ": " << *vfp1 << endl;
		++vfp1;
	}
	cout << endl;

	Base2& b2 = d;
	VFP* vfp2 = (VFP*)*(int *)&b2;
	cout << "Base2 vir table:" << endl;
	while (*vfp2)
	{
		(*vfp2)();
		cout << ": " << *vfp2 << endl;
		++vfp2;
	}
	cout << endl;
}
   数据模型:                                              虚表剖析:                                                                                                                

  浅谈c++虚函数 虚继承的虚表剖析_第4张图片浅谈c++虚函数 虚继承的虚表剖析_第5张图片 

  

   (3)菱形继承

    

class Base
{
public:
	Base()
	{}
	virtual void Test1()
	{
		cout << "Base::Test1()";
	}
	int data1;
};
class C1 :public Base
{
public:
	virtual void Test1()
	{
		cout << "C1::Test1()";
	}
	virtual void Test2()
	{
		cout << "C1::Test2()";
	}
	int data2;
};
class C2 :public Base
{
public:
	virtual void Test1()
	{
		cout << "C2::Test1()";
	}
	virtual void Test3()
	{
		cout << "C2::Test3()";
	}
	
	int data3;
};
class D :public C1, public C2
{
public:
	virtual void Test1()
	{
		cout << "D::Test1()" ;
	}
	virtual void Test2()
	{
		cout << "D::Test2()" ;
	}
	virtual void Test3()
	{
		cout << "D::Test3()";
	}
	virtual void Test4()
	{
		cout << "D::Test4()";
	}
	int data4;
};
typedef void(*VFP)();
void PrintVFP()
{
	D d;
	d.C1::data1 = 0;
	d.C2::data1 = 1;
	d.data2 = 2;
	d.data3 = 3;
	d.data4 = 4;
	C1& c1 = d;
	VFP* vfp1 = (VFP*)*(int *)&c1;
	cout << "C1 vir table:" << endl;
	while (*vfp1)
	{
		(*vfp1)();
		cout <<" : " <<*vfp1 << endl;
		++vfp1;
	}
	cout << endl;

	C2& c2 = d;
	VFP* vfp2 = (VFP*)*(int *)&c2;
	cout << "C2 vir table:" << endl;
	while (*vfp2)
	{
		(*vfp2)();
		cout << " : " << *vfp2 << endl;
		++vfp2;
	}
	cout << endl;
}
 虚表剖析:                                                                                                          数据模型:

  浅谈c++虚函数 虚继承的虚表剖析_第6张图片       浅谈c++虚函数 虚继承的虚表剖析_第7张图片

      说明: 如果派生类D有新的虚函数,则添加到第一继承顺序的基类c1的虚表后面

                  该菱形继承存在二义性,c1和c2中都继承了base的成员变量

     菱形继承的大小:28   c1(虚表指针+base成员+c1成员 12) + c2(12) + 派生类D的成员

 2 虚继承

   (1)单继承

     

class Base
{
public:
	Base()
		:data1(33)
	{}
	virtual void Test1()
	{
		cout << "Base::Test1()";
	}
	virtual void Test2()
	{
		cout << "Base::Test2()";
	}
	virtual void Test3()
	{
		cout << "Base::Test3()";
	}
	int data1;

};
class Derived :virtual public Base
{
public:
	Derived() // 1填写偏移量表格地址 2调用基类构造函数(填写基类虚表地址) 3填写派生类虚表地址
		      //4 重新填写属于基类对象部分的虚表地址(用派生类的虚表) 5派生类对象和基类对象之间用0分割(虚拟继承中有构造或析构才会用0)
	{}
	~Derived()
	{}
	virtual void Test1()
	{
		cout << "Derived::Test1()";
	}
	virtual void Test3()
	{
		cout << "Derived::Test3()" ;
	}
	virtual void Test4() // 屏蔽掉 大小为16  没有第一个虚表
	{
		cout << "Derived::Test4()";
	}
	int data2;
};
void TestSize()
{
	Derived d;
	d.data1 = 1;
	d.data2 = 2;
	cout << sizeof(Derived) << endl;  // 24 去掉析构函数和构造函数 20 多加四个字节	
}
typedef void(*VFP)();
void PrintVfp()
{
	Derived d;
	d.data1 = 1;
	d.data2 = 2;
	VFP* vfp = (VFP*)*(int *)&d;
	cout << "Derived vir table  1:" << endl;
	while (*vfp)
	{
		(*vfp)();
		cout << ": " << *vfp << endl;
		++vfp;
	}
	cout << endl;

	Base& b = d;
	VFP* vfp1 = (VFP*)*(int *)&b;
	cout << "Derived vir table: 2 Base" << endl;
	while (*vfp1)
	{
		(*vfp1)();
		cout << ": " << *vfp1 << endl;
		++vfp1;
	}
	cout << endl;
}
   虚表剖析:

   a  没有构造函数和析构函数(少中间的0 四个字节),派生类有新的虚函数
   浅谈c++虚函数 虚继承的虚表剖析_第8张图片
    b 没有构造函数和构造函数(少中间的0 四个字节)   c。有构造函数或者析构函数

       派生类没有新的虚函数                                                     派生类新定义了虚函数

    浅谈c++虚函数 虚继承的虚表剖析_第9张图片                                     浅谈c++虚函数 虚继承的虚表剖析_第10张图片

    简述一下构造函数的作用:(派生类的构造函数做了什么)

     

    

(2)多继承

     没有考虑构造函数或析构函数 ,派生类定义了新虚函数

class C1
{
public:
	virtual void Test1()
	{
		cout << "C1::Test1()";
	}
	virtual void Test2()
	{
		cout << "C1::Test2()";
	}
	int data1;
};
class C2
{
public:
	virtual void Test3()
	{
		cout << "C2::Test3()";
	}
	virtual void Test4()
	{
		cout << "C2::Test4()";
	}
	int data2;
};
class D :public virtual C1, public virtual C2
{
public:
	virtual void Test1() //重写c1的Test1
	{
		cout << "D::Test1()";
	}
	virtual void Test3() //重写c2的Test3
	{
		cout << "D::Test3()";
	}
	virtual void Test5() //派生类特有的Test5
	{
		cout << "D::Test5()";
	}
	int data3;
};
typedef void(*VFP)();
void PrintVfp()
{

	D d;
	d.data3 = 3;
	d.data2 = 2;
	d.data1 = 1;
	
	VFP* vfp3 = (VFP*)*(int *)&d;
	cout << " 派生类自己特有的虚表:" << endl;
	while (*vfp3)
	{
		(*vfp3)();
		cout << ": " << *vfp3 << endl;
		++vfp3;
	}
	cout << endl;

	C1& c1 = d;
	VFP* vfp1 = (VFP*)*(int *)&c1;
	cout << " c1的虚表:" << endl;
	while (*vfp1)
	{
		(*vfp1)();
		cout << ": " << *vfp1 << endl;
		++vfp1;
	}
	cout << endl;

	C2& c2 = d;

	VFP* vfp2 = (VFP*)*(int *)&c2;
	cout << " c2的虚表:" << endl;
	while (*vfp2)
	{
		(*vfp2)();
		cout << ": " << *vfp2 << endl;
		++vfp2;
	}
	cout << endl;
}
  剖析虚表:

   

   (3)菱形虚拟继承,解决了二义性

        没有构造函数或析构函数,派生类类定义了新的虚函数

class Base
{
public:
	Base()
		:_data1(0)
	{}

	virtual void Test1()
	{
		cout << "Base::Test1()" ;
	}
	int _data1;

};
class C1 :virtual public Base
{
public:
	virtual void Test1()
	{
		cout << "C1::Test1()" ;
	}
	virtual void Test2()
	{
		cout << "C1::Test2()"  ;
	}
	int _data2;
};
class C2 :virtual public Base
{
public:
	virtual void Test1()
	{
		cout << "C2::Test1()" ;
	}
	virtual void Test3()
	{
		cout << "C2::Test3()" ;
	}
	int _data3;
};
class D :public C1, public C2
{
public:
	virtual void Test1()
	{
		cout << "D::Test1()" ;
	}
	virtual void Test2()
	{
		cout << "D::Test2()" ;
	}
	virtual void Test3()
	{
		cout << "D::Test3()" ;
	}
	virtual void Test4()
	{
		cout << "D::Test4()";
	}
	int _data4;
};
typedef void(*VFP)();
void PrintVfp()
{

	D d;
	d._data1 = 1;
	d._data2 = 2;
	d._data3 = 3;
	d._data4 = 4;
	C1& c1 = d;
	VFP* vfp1 = (VFP*)*(int *)&c1;
	cout << " vir table up:" << endl;
	while (*vfp1)
	{
		(*vfp1)();
		cout << ": " << *vfp1 << endl;
		++vfp1;
	}
	cout << endl;

	C2& c2 = d;

	VFP* vfp2 = (VFP*)*(int *)&c2;
	cout << " vir table mid:" << endl;
	while (*vfp2)
	{
		(*vfp2)();
		cout << ": " << *vfp2 << endl;
		++vfp2;
	}
	cout << endl;

	Base& b = d;
	VFP* vfp3 = (VFP*)*(int *)&b;
	cout << " vir table down:" << endl;
	while (*vfp3)
	{
		(*vfp3)();
		cout << ": " << *vfp3 << endl;
		++vfp3;
	}
	cout << endl;
}
  

  

     

你可能感兴趣的:(C/C++)