返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++的多态和虚函数实例分析
  • 425
分享到

C++的多态和虚函数实例分析

2023-06-29 04:06:45 425人浏览 独家记忆
摘要

这篇文章主要介绍了c++的多态和虚函数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++的多态和虚函数实例分析文章都会有所收获,下面我们一起来看看吧。一、C++的面试常考点阿里虽然是国内Java的第一

这篇文章主要介绍了c++的多态和虚函数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++的多态和虚函数实例分析文章都会有所收获,下面我们一起来看看吧。

    一、C++的面试常考点

    阿里虽然是国内Java的第一大厂但是并非所有的业务都是由Java支撑,很多服务和中下层的存储,计算,网络服务,大规模的分布式任务都是由C++编写。在阿里所有部门当中对C++考察最深的可能就是阿里云

    阿里对C++的常考点:

    STL 容器相关实现

    C++新特性的了解

    多态和虚函数的实现

    指针的使用

    二、阿里真题

    2.1 真题一

    现在假设有一个编译好的C++程序,编译没有错误,但是运行时报错,报错如下:你正在调用一个纯虚函数(Pure virtual function call error),请问导致这个错误的原因可能是什么?

    纯虚函数调用错误一般由以下几种原因导致:

    • 从基类构造函数直接调用虚函数。(直接调用是指函数内部直接调用虚函数)

    • 从基类析构函数直接调用虚函数。

    • 从基类构造函数间接调用虚函数。(间接调用是指函数内部调用其他的非虚函数,其内部直接或间接地调用了虚函数)

    • 从基类析构函数间接调用虚函数。

    • 通过悬空指针调用虚函数。

    注意:其中1,2编译器会检测到此类错误。3,4,5编译器无法检测出此类情况,会在运行时报错。

    (1)虚函数表vtbl

    编译器在编译时期为每个带虚函数的类创建一份虚函数表

    实例化对象时, 编译器自动将类对象的虚表指针指向这个虚函数表

    (2)构造一个派生类对象的过程

    1.构造基类部分:

    • 构造虚表指针,将实例的虚表指针指向基类的vtbl

    • 构造基类的成员变量

    • 执行基类的构造函数函数体

    2.递归构造派生类部分:

    • 将实例的虚表指针指向派生类vtbl

    • 构造派生类的成员变量

    • 执行派生类的构造函数体

    (3)析构一个派生类对象的过程

    1.递归析构派生类部分:

    • 将实例的虚表指针指向派生类vtbl

    • 执行派生类的析构函数体

    • 析构派生类的成员变量(这里的执行函数体,析构派生类成员变量,两者的顺序和构造的步骤是相反的)

    2.析构基类部分:

    • 将实例的虚表指针指向基类的vtbl

    • 执行基类的析构函数函数体

    • 析构基类的成员变量

    构造函数和析构函数执行函数体时,实例的虚函数表指针,指向构造函数和析构函数本身所属的类的虚函数表,此时执行的虚函数,即调用的本身的该类本身的虚函数,下面是一个【间接调用】的栗子:基类中的析构函数中,调用纯虚函数(该虚函数就在基类中定义)。

    #include <iOStream>using namespace std;class Parent {public://纯虚函数    virtual void virtualFunc() = 0;    void helper() {        virtualFunc();    }    virtual ~Parent(){        helper();    }};class Child : public Parent{    public:    void virtualFunc() {        cout << "Child" << endl;    }    virtual ~Child(){}};int main() {    Child child;//system("pause");    return 0;}

    运行时报错libc++abi.dylib: Pure virtual function called

    C++的多态和虚函数实例分析

    2.2 真题二

    在构造实例过程当中一部分是初始化列表一部分是在函数体内,你能说一下这些的顺序是什么?差别是什么和this指针构造的顺序

    顺序:

    (1)初始化列表中的先初始化。

    (2)执行函数体代码。

    • 执行类中函数体,如执行构造函数时,所有成员已经初始化完毕了;

    • this指针属于对象,而对象还没构造完成前,若使用this指针,编译器会无法识别。在初始化列表中显然不能使用this指针,注意:在构造函数体内部可以使用this指针。

    构造函数的执行可以分成两个阶段:

    • 初始化阶段:所有类类型的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中。

    • 计算赋值阶段:一般用于执行构造函数体内的赋值操作。

    #include <iostream>using namespace std;class Test1 {public:    Test1(){    cout << "Construct Test1" << endl;    }//拷贝构造函数    Test1& operator = (const Test1& t1) {    cout << "Assignment for Test1" << endl;        this->a = t1.a;        return *this;    }    int a ;};class Test2 {public:    Test1 test1;//Test2的构造函数    Test2(Test1 &t1) {    cout << "构造函数体开始" << endl;        test1 = t1 ;        cout << "构造函数体结束" << endl;    }};int main() {    Test1 t1;    Test2 test(t1);system("pause");    return 0;}

    C++的多态和虚函数实例分析

    分析上面的结果:

    (1)第一行结果即Test t1实例化对象时,执行Test1的构造函数;

    (2)第二行代码,实例化Test2对象时,在执行Test2构造函数时,正如上面所说的,构造函数的第一步是初始化阶段:所有类类型的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中。所以Test2在构造函数体执行之前已经使用了Test1的默认构造函数初始化好了t1。打印出Construct Test1

    这里的拷贝构造函数中可以使用this指针,指向当前对象。

    (3)第三四五行结果:执行Test2的构造函数。

    2.3 真题三

    初始化列表的写法和顺序有没有什么关系?

    构造函数的初始化列表中的前后位置,不影响实际标量的初始化顺序。成员初始化的顺序和它们在类中的定义顺序一致。

    必须使用初始化列表的情况:数据成员是const、引用,或者属于某种未提供默认构造函数的类类型。

    2.4 真题四

    在普通的函数当中调用虚函数和在构造函数当中调用虚函数有什么区别?

    普调函数当中调用虚函数是希望运行时多态。而在构造函数当中不应该去调用虚函数因为构造函数当中调用的就是本类型当中的虚函数,无法达到运行时多态的作用。

    2.5 真题五

    成员变量,虚函数表指针的位置是怎么排布?

    如果一个类带有虚函数,那么该类实例对象的内存布局如下:

    • 首先是一个虚函数指针,

    • 接下来是该类的成员变量,按照成员在类当中声明的顺序排布,整体对象的大小由于内存对齐会有空白补齐。

    • 其次如果基类没有虚函数但是子类含有虚函数:

      • 此时内存子类对象的内存排布也是先虚函数表指针再各个成员。

    如果将子类指针转换成基类指针此时编译器会根据偏移做转换。在visual studio,x64环境下测试,下面的Parent p = Child();是父类对象,由子类来实例化对象。

    #include <iostream>using namespace std;class Parent{public:    int a;    int b;};class Child:public Parent{public:    virtual void test(){}    int c;};int main() {    Child c = Child();    Parent p = Child();    cout << sizeof(c) << endl;//24    cout << sizeof(p) << endl;//8    Child* cc = new Child();    Parent* pp = cc;    cout << cc << endl;//0x7fbe98402a50    cout << pp << endl;//0x7fbe98402a58cout << endl << "子类对象abc成员地址:" << endl;    cout << &(cc->a) << endl;//0x7fbe98402a58    cout << &(cc->b) << endl;//0x7fbe98402a5c    cout << &(cc->c) << endl;//0x7fbe98402a60system("pause");    return 0;}

    结果如下:

    24
    8
    0000013AC9BA4A40
    0000013AC9BA4A48

    子类对象abc成员地址:
    0000013AC9BA4A48
    0000013AC9BA4A4C
    0000013AC9BA4A50
    请按任意键继续. . .

    分析上面的结果:

    (1)第一行24为子类对象的大小,首先是虚函数表指针8B,然后是2个继承父类的int型数值,还有1个是该子类本身的int型数值,最后的4是填充的。

    (2)第二行的8为父类对象的大小,该父类对象由子类初始化,含有2个int型成员变量。

    (3)子类指针cc指向又new出来的子类对象(第三个),然后父类指针pp指向这个子类对象,这两个指针的值:

    • 父类指针pp值:0000013AC9BA4A48

    • 子类指针cc值:0000013AC9BA4A40

    即发现如之前所说的:如果将子类指针转换成基类指针此时编译器会根据偏移做转换。我测试环境是64位,所以指针为8个字节。转换之后pp和cc相差一个虚表指针的偏移。

    (4)&(cc->a)的值即 0000013AC9BA4A48,和pp值是一样的,注意前面的 0000013AC9BA4A40到0000013AC9BA4A47其实就是子类对象的虚函数表指针了。

    关于“C++的多态和虚函数实例分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C++的多态和虚函数实例分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网其他教程频道。

    --结束END--

    本文标题: C++的多态和虚函数实例分析

    本文链接: https://lsjlt.com/news/322560.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • C++的多态和虚函数实例分析
      这篇文章主要介绍了C++的多态和虚函数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++的多态和虚函数实例分析文章都会有所收获,下面我们一起来看看吧。一、C++的面试常考点阿里虽然是国内Java的第一...
      99+
      2023-06-29
    • C++虚函数表与多态实例代码分析
      这篇文章主要介绍“C++虚函数表与多态实例代码分析”,在日常操作中,相信很多人在C++虚函数表与多态实例代码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++虚函数表与多态实例代码分析”的疑惑有所帮助!...
      99+
      2023-07-05
    • C++虚函数和多态超详细分析
      目录1.什么是虚函数2.纯虚函数3.c++多态4.纯虚函数和ADT过程5.虚析构函数6.dynamic_cast类型转换7.成员函数指针 1.什么是虚函数 C++类中用virtual...
      99+
      2023-01-28
      C++虚函数和多态 C++虚函数 C++多态
    • C/C++多态原理实例分析
      本篇内容介绍了“C/C++多态原理实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!多态面向对象编程有三大特性:继承、封装和多态。其中,...
      99+
      2023-07-02
    • 关于虚函数实现多态的原理及分析
      目录1、C++中如何实现多态2、虚函数实现多态的原理2.1 单类继承2.2 多类继承示例总结1、C++中如何实现多态 基类中先声明一个虚函数至少有一个继承该基类的子类 2、虚函数实现...
      99+
      2023-02-05
      虚函数 虚函数实现多态 多态的原理
    • 深入解析C++中的虚函数与多态
      1.C++中的虚函数C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类...
      99+
      2022-11-15
      虚函数 多态
    • C++中多态的示例分析
      小编给大家分享一下C++中多态的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1. 多态概念1.1 概念多态的概念:通俗来说,就是多种形态,具体点就是去完...
      99+
      2023-06-15
    • C++的多态和虚函数你真的了解吗
      目录一、C++的面试常考点二、阿里真题2.1 真题一(1)虚函数表vtbl(2)构造一个派生类对象的过程(3)析构一个派生类对象的过程2.2 真题二2.3 真题三2.4 真题四2.5...
      99+
      2024-04-02
    • C++函数参数实例分析
      这篇文章主要介绍了C++函数参数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++函数参数实例分析文章都会有所收获,下面我们一起来看看吧。一、函数参数的默认值C++ 中可以在函数声明时为参数提供一个默...
      99+
      2023-06-30
    • 深入解析C++中多态性和虚函数使用原理
      目录1.为什么需要virtual2.纯虚函数和抽象类3.构造函数与虚函数4.虚析构函数与纯虚析构函数5.纯虚析构函数的应用1.为什么需要virtual 按照Java的思维方式,在有了...
      99+
      2023-05-20
      C++ 多态性虚函数 C++ 多态性 C++ 虚函数
    • C++的多态与虚函数是什么
      这篇文章主要介绍“C++的多态与虚函数是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++的多态与虚函数是什么”文章能帮助大家解决问题。多态性多态性是面向对象程序设计的关键技术之一,若程序设计...
      99+
      2023-06-29
    • C++的多态与虚函数你了解吗
      目录多态性虚函数总结多态性 多态性是面向对象程序设计的关键技术之一,若程序设计语言不支持多态性,不能称为面向对象的语言,利用多态性技术,可以调用同一个函数名的函数,实现完全不同的功能...
      99+
      2024-04-02
    • 深入了解C++的多态与虚函数
      目录1.多态的机制与虚函数的机制1.1 多态的机制1.2 虚函数的机制1.3虚函数表的结构图1.4 动态多态实现的三个前提件(很重要)2.多态实例应用3.多态的巨大问题与虚析构3.1...
      99+
      2024-04-02
    • C++ 虚拟函数深入剖析:类型擦除与多态实现
      c++++虚函数实现多态,通过类型擦除将对象类型信息分离,使编译器仅识别公共接口。虚指针表存储虚函数地址,当基类指针指向派生类对象时,指向派生类虚指针表的派生类指针将替代基类指针指向的虚...
      99+
      2024-04-29
      c++ 虚拟函数
    • 详解C++虚函数中多态性的实现原理
      目录什么是虚函数多态性的实现多态的底层原理多态性的好处总结在面向对象的编程中,多态性是一个非常重要的概念。多态性意味着在不同的上下文中使用同一对象时,可以产生不同的行为。C++是一种...
      99+
      2023-05-19
      C++虚函数的多态性原理 C++虚函数 多态性 C++虚函数
    • C++中的多态问题—理解虚函数表及多态实现原理
      目录一、多态的概念概念构成条件二、虚函数的重写重写的定义重写的特殊情况override和final关键字区分重写、重载、重定义抽象类的概念三、多态的实现原理父类对象模型补充:生成默认...
      99+
      2023-02-05
      C++中的多态 C++虚函数表 C++多态实现原理
    • C语言的div()函数实例分析
      本文小编为大家详细介绍“C语言的div()函数实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言的div()函数实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。...
      99+
      2024-04-02
    • C#动态数组的示例分析
      小编给大家分享一下C#动态数组的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!C#动态数组的详解实例:ArrayList AL =&n...
      99+
      2023-06-17
    • C++虚函数表和虚析构介绍
      目录1、虚函数表2、虚析构1、虚函数表 虚函数表是C++实现多态的基础,多态是面向对象的三大特性之一,多态有利于提高代码的可读性,便于后期代码的扩展和维护。我们都知道多态的实现是基于...
      99+
      2024-04-02
    • java多态应用实例分析
      这篇文章主要讲解了“java多态应用实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java多态应用实例分析”吧!本教程操作环境:windows7系统、java10版,DELL G3电...
      99+
      2023-06-30
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作