一,概念等基础
1)多态的定义
通俗来说就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
举个例子:不同的人去买高铁票,同样的行为,因为身份的不同,有的人买的是学生票,有些人是儿童票,有些人是普通票,也就是多种形态去做同一个事会产生不同的状态。
2)虚函数
虚函数是多态的重要组成部分。
定义:即被virtual修饰的类成员函数称为虚函数。
class Person { public: virtual void BuyTicket() { cout << "买票-全价" << endl;} };
3)构成多态的条件
1. 必须通过基类的指针或者引用调用虚函数
2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
4)虚函数的作用
虚函数在被继承类里面被重写之后,调用这个函数就会满足多态,接下来看代码。
class A { public: virtual void func() { cout << "a"; } }; class B :public A{ public: virtual void func() { cout << "b"; } }; void test(A& a){ a.func(); } int main(){ B b; test(b); return 0; }
运行结果:b
这就是因为在a掉用func函数时满足了多态的调用,会通过a指向空间里面的func函数来调用,而不是A里面的func函数。这样子就能让不同的对象去做相同的动作而产生不同的状态。
小细节:使用析构函数的多态,这样可以做到通过底层空间来调用析构函数,防止内存泄漏。
二,多态原理
1)虚指针
在VS2019里面创建一个类,里面有虚函数
class A { public: virtual void func() { cout << "a"; } };
打开监视窗口,监视a
a里面有_vf这是什么?它在a的前四个字节,首先我们能发现这是一个二级指针,指针里面是一个函数指针,我们把_vf称为虚指针,虚指针指向一个包括函数的表,这个表称为虚函数表,进一步探索我们能知道这个指针是a里面所有的虚函数地址,通过这个地址我们能调用虚函数。
2)如何拿到这个虚指针
在C++中我们想要拿到这个地址,我们首先要知道每个类的地址是连续的,所以想要拿到虚指针,可以通过地址的偏移来拿到虚指针,通过虚指针找到虚函数的地址实现调用虚函数。
3)到底如何实现多态
首先在继承的时候会把这个虚指针指向的虚函数表继承下来,继承之后,如果虚函数被重写了,那么虚函数表的地址就会被新的虚函数地址覆盖,如果没有重写就不会改变。如果本身也有虚函数的话,那么自身的虚函数就会在继承的所有类的第一个类的虚函数表后面按顺序加上,然后才会加上其他继承类的虚函数表(多继承)。在调用的时候会根据底层的地址减去偏移量拿到虚指针,通过虚指针里面的地址来调用函数,因为虚函数表被重写的函数已经被覆盖率,那么就可以达到根据底层来调用虚函数。
注:如果大家对文章有疑惑或者发现了文章的错误,本人是在校大学生,会经常查看评论区的,大家不妨耐住耐心等我回答。