一. 多态的实现--虚表
1.多态就是多种形态。在C++中,对同一父类和子类构造出的不同对象发出同一条指令,需要它们完成不同的工作,就需要在父类和子类写出相同函数名的函数方法,并用虚函数区分它们。父类的指针/引用调用重写的虚函数,当父类指针/引用指向父类对象时调用的是父类的虚函数,指向子类对象时调用的是子类的虚函数。
2.虚函数表是通过一块连续内存来存储虚函数的地址。这张表解决了继承、虚函数(重写)的问题。在有虚函数的对象实例中都存在一张虚函数表,虚函数表就像一张地图,指明了实际应该调用的虚函数函数。
//带虚函数的类
class Base
{
public:
virtual void func1()
{
cout << "Base::func1()" << endl;
}
virtual void func2()
{
cout << "Base::func2()" << endl;
}
private:
int a;
};
void Test1()
{
Base b1;
}
3.带虚函数的类的模型结构
4.同一类的对象共用同一虚表
void Test2()
{
Base b1, b2, b3;
}
二. 单继承&多继承的对象模型
1.单继承:
class Base
{
public:
virtual void func1()
{
cout << "Base::func1()" << endl;
}
virtual void func2()
{
cout << "Base::func2()" << endl;
}
private:
int a;
};
class Derive :public Base
{
public:
virtual void func1()
{
cout << "Derive::func1" << endl;
}
virtual void func3()
{
cout << "Derive::func3" << endl;
}
virtual void func4()
{
cout << "Derive::func4" << endl;
}
private:
int b;
};
typedef void(*FUNC) ();
void PrintVTable(int* VTable)
{
cout << " 虚表地址>" << VTable << endl;
for (int i = 0; VTable[i] != 0; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,->", i, VTable[i]);
FUNC f = (FUNC)VTable[i];
f();
}
cout << endl;
}
void Test1()
{
Base b1;
Derive d1;
int* VTable1 = (int*)(*(int*)&b1);
int* VTable2 = (int*)(*(int*)&d1);
PrintVTable(VTable1);
PrintVTable(VTable2);
}
2.多继承
class Base1
{
public:
virtual void func1()
{
cout << "Base1::func1" << endl;
}
virtual void func2()
{
cout << "Base1::func2" << endl;
}
private:
int b1;
};
class Base2
{
public:
virtual void func1()
{
cout << "Base2::func1" << endl;
}
virtual void func2()
{
cout << "Base2::func2" << endl;
}
private:
int b2;
};
class Derive : public Base1, public Base2
{
public:
virtual void func1()
{
cout << "Derive::func1" << endl;
}
virtual void func3()
{
cout << "Derive::func3" << endl;
}
private:
int d1;
};
typedef void(*FUNC) ();
void PrintVTable(int* VTable)
{
cout << " 虚表地址>" << VTable << endl;
for (int i = 0; VTable[i] != 0; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,->", i, VTable[i]);
FUNC f = (FUNC)VTable[i];
f();
}
cout << endl;
}
void Test1()
{
Derive d1;
int* VTable = (int*)(*(int*)&d1);
PrintVTable(VTable);
// Base2虚函数表在对象Base1后面
VTable = (int *)(*((int*)&d1 + sizeof(Base1) / 4));
PrintVTable(VTable);
}
三. 静态多态和动态多态
1.静态多态就是重载,因为是在编译期决议确定,所以称为静态多态。
2.动态多态就是通过继承重写基类的虚函数实现的多态,因为是在运行时决议确定,所以称为动态多态。
class Base
{
public:
virtual void func1()
{
cout << "Base::func1" << endl;
}
virtual void func2()
{
cout << "Base::func2" << endl;
}
void display()
{
cout << "display()" << endl;
}
void display(int i)
{
cout << "display(int i)->" << i << endl;
}
private:
int a;
};
class Derive :public Base
{
public:
virtual void func1()
{
cout << "Derive::func1" << endl;
}
virtual void func3()
{
cout << "Derive::func3" << endl;
}
virtual void func4()
{
cout << "Derive::func4" << endl;
}
private:
int b;
};
void func(Base& b)
{
b.func1();
b.display();
b.display(10);
}
void Test1()
{
Base b1;
Derive d1;
func(b1);
func(d1);
}
四. 菱形虚拟继承的对象模型
class A
{
public:
virtual void FunTest1()
{
cout << "A::FunTest1()" << endl;
}
virtual void FunTest2()
{
cout << "A::FunTest2()" << endl;
}
private:
int _a;
};
class B1 :virtual public A
{
public:
virtual void FunTest3()
{
cout << "B1::FunTest3()" << endl;
}
virtual void FunTest4()
{
cout << "B2::FunTest4()" << endl;
}
private:
int _b1;
};
class B2 :virtual public A
{
public:
virtual void FunTest1()
{
cout << "B2::FunTest1()" << endl;
}
virtual void FunTest4()
{
cout << "B2::FunTest4()" << endl;
}
private:
int _b2;
};
class C :public B1, public B2
{
public:
virtual void FunTest1()
{
cout << "C::FunTest1()" << endl;
}
virtual void FunTest5()
{
cout << "C::FunTest5()" << endl;
}
private:
int _c;
};
void Test1()
{
C c;
c.FunTest5();
}
可见,在虚拟继承中,无论是几重继承,最终子类的虚函数表总是与继承列表的第一个父类的虚函数表合并在一起,但是有覆盖的虚函数,自然去覆盖父类的同名虚函数,并合并在该父类的虚表中。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。