版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}
普通函数:直接调用
虚函数的调用(满足多态条件)
- 从对象前4个字节中取虚表的地址
- 传递this指针
- 从虚表中获取虚函数的地址(在虚表地址+虚函数在虚表中的偏移量)
- 调用虚函数
单继承
- 基类有虚函数,继承基类,派生类将基类的虚表拷贝到自己的虚表中
- 派生类某个虚函数如果重写基类的虚函数,替代相同偏移量位置的虚函数为子类的虚函数
- 如果派生类新增加自己特有的虚函数,将其放在基类继承下来虚函数的后面。
#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;
}
带有虚函数的多继承对象的模型以及虚表
- 多继承,将派生类自己的新增加的虚函数添加到第一张虚表最后
#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;
}