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++;
}
}
剖析 虚表
说明:虚函数按声明顺序存在于虚表中;
在派生类中,前面是基类的虚函数,后面是派生类的虚函数
(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
}
虚表剖析
派生类虚表的形成: 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;
}
数据模型: 虚表剖析:
(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;
}
虚表剖析: 数据模型:
说明: 如果派生类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 四个字节),派生类有新的虚函数
b 没有构造函数和构造函数(少中间的0 四个字节) c。有构造函数或者析构函数
派生类没有新的虚函数 派生类新定义了虚函数
简述一下构造函数的作用:(派生类的构造函数做了什么)
(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;
}