gpt4 book ai didi

深入解析C++中的虚函数与多态

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章深入解析C++中的虚函数与多态由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

1.C++中的虚函数 C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议.

对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)和一个指向虚函数表的指针(vptr)来实现的。虚函数表,简称为vtbl,虚函数表表对实现多态起着至关重要的作用。在这个表中,主要保存了一个类中的虚函数的地址,这张表解决了继承、覆盖的问题,保证其内容能真实反应实际的函数。每一个包含虚函数的类的实例都包含一个cptr指针,指向虚函数表的首地址。我们可以通过这个指针找到要访问的虚函数的,完成虚函数的调用主要包括:找到虚函数表的首地址(vptr),通过cptr找到要使用虚函数地址,调用虚函数。那么使用虚函数大家总要考虑效率的问题,实际上为了提高效率,C++的编译器是保证虚函数表的指针存在于对象实例中最前面的位置,这是为了保证取到虚函数表的有最高的性能,这意味着我们通过对象实例的地址得到这张虚函数表,然后通过遍历表就可以找到其中的虚函数的地址,然后调用相应的函数。不妨看看下面的代码:

复制代码 代码如下:

#include <iostream> 。

  。

using namespace std,

class Base { public:     virtual void f() { cout << "Base::f" << endl; }     virtual void g() { cout << "Base::g" << endl; }     virtual void h() { cout << "Base::h" << endl; } },

typedef void(*Fun)(void),

int main() {     Base b;     Fun pFun = NULL;     cout << "虚函数表地址:" << (int*)(&b) << endl;     cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;     pFun = (Fun)*((int*)*(int*)(&b));     pFun();     return 0; } 。

通过这个示例,可以看到,通过强行把&b转成int *,取得虚函数表的地址(vptr),然后,再次取址就可以得到第一个虚函数的地址了,也就是Base::f(),这在上面的程序中得到了验证(把int* 强制转成了函数指针)。通过这个示例,我们就可以知道如果要调用Base::g()和Base::h(),其代码如下:

复制代码 代码如下:

(Fun)*((int*)*(int*)(&b)+0); // Base::f() (Fun)*((int*)*(int*)(&b)+1); // Base::g() 。

  。

(Fun)*((int*)*(int*)(&b)+2); // Base::h() 。

可以看看虚函数表的图是怎么画的:

  。

        深入解析C++中的虚函数与多态    

大家都知道,多态是通过继承实现的,那么我们要说说虚函数继承的问题。继承就涉及到了虚函数的覆盖了,实际上不被覆盖的虚函数和多态又有什么联系呢?这里我们讨论有覆盖的虚函数表是什么样的,假设存在下面的继承关系:

        深入解析C++中的虚函数与多态

看看虚函数表示什么样的:

        深入解析C++中的虚函数与多态

可以发现,Base::f()被覆盖了,这样若把Derive的实例赋值给一个基类Base指针pBase,通过pBase->f();则访问的是子类中的f()也就是完成了多态。那么虚函数表中的内容到底是怎么样的呢?可以看看下面的四句话就会明白! 。

1.虚函数按照其声明顺序放于表中.

2.父类的虚函数在子类的虚函数前面.

3.覆盖的f()函数被放到了虚表中原来父类虚函数的位置.

4.没有被覆盖的函数依旧.

2.用虚函数实现多态 看看下面的多态的代码:

复制代码 代码如下:

#include <iostream> 。

  。

using namespace std,

class Base { public:     virtual void Print()     {         cout<<"Base::Print()"<<endl;     } }; class Derive : public Base { public:     virtual void Print()     {         cout<<"Derive::Print()"<<endl;     } }; int main() {     Derive derive;     Base *pBase = &derive;     pBase->Print();     return 0; } //多态代码 。

实现虚函数的代码,一定要切记:一定是基类的指针指向子类的对象的地址。首先试着理解一下用虚函数实现多态的原理,如果实在没理解为什么虚函数能实现多态,又为什么这样实现多态,上网再搜一搜相关的资料!!! 。

最后此篇关于深入解析C++中的虚函数与多态的文章就讲到这里了,如果你想了解更多关于深入解析C++中的虚函数与多态的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com