`
tinggo
  • 浏览: 43539 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

深入理解C++中多态的实现

阅读更多
对于C++中多态性是面向对象中很重要的特性之一,每种面向对象的语言对于多态的实现都不尽相同。

最近,学习中发现一段既陌生又熟悉的代码,大致情况如下#include

#include <iostream>

using namespace std;

class BaseClass
{
public:
    virtual void Display()
    {
        cout<<"BaseClass::Display()"<<endl;
    }

    virtual void Display(int a)
    {
        cout<<"BaseClass::Display(int a)"<<endl;
    }
};

class ExtendClass:public BaseClass
{
public:
    virtual void Display()
    {
        cout<<"ExtendClass::Display()"<<endl;
    }

    virtual void Display(int a)
    {
        cout<<"ExtendClass::Display(int a)"<<endl;
    }

    virtual void Display(float a)
    {
        cout<<"ExtendClass::Display(float)"<<endl;
    }
};

int main()
{
    BaseClass* ptrBaseClass = new BaseClass();
    ptrBaseClass->Display();
    ptrBaseClass->Display(1);
    ptrBaseClass->Display(1.1);
    return 0;
}


代码的核心思想是
1.基类实现了多个虚函数
2.子类继承基类并且override所有虚函数
3.作者发现子类应该“重载一下”以满足需求,这样的需求原因可能很多

代码即熟悉是因为,overload(重载)的需求在实际应用中很多,因此不感到奇怪。
陌生的原因是,这种写法感觉很奇怪,没见过(因为是错误的,所以没人这么写)

输出结果为
BaseClass::Display()
BaseClass::Display(int a)
BaseClass::Display(int a)

并且在编译是编译器发出强制将float转换为int的警告

首先效果肯定不是原有作者要的结果,然后我开始分析原因
根据Thinking in C++中对于vptr和vtable的解释,貌似我无法找到与这种现象有关的详细解释,也许是我没有发现。

随后我便开始自己解释:
既然所有的虚函数都存放在vtable中,那么指针通过vptr查找到vtable中虚函数时,应该也能找到“float”版的函数。但是他为什么就会去调用int版本呢?通过以往经验我查看了反汇编
发现调用int和调用float部分的汇编代码一模一样,我开始认为这一切的原因出在了编译过程中。可是我始终无法从vptr和vtable的角度出发进行解释这种现象。

最后在请教了高人之后,知道了一件很重要但始终被我误解的事(都是以前教条主义惹得祸,当时学的时候就应该追根溯源)。

当诸如ptrBaseClass->Display();话出现时,编译器是如何解释的呢?
1.因为指针是基类的,因此他将查看基类的所有函数,查看是否满足要求的。
2.如果查看到且查看到的函数发现是virtual的,则在翻译成汇编时翻译成:请到vtable中偏移地址为XXX的地方寻找代码。
3.如果不是virtual,则直接把基类的代码地址获得
4.如果没有在基类的函数中查找到相同的函数,则报出找不到的错误

发现没有,其实多态在C++中的实现还是根据基类的指针来查看函数是否合法。
做个实验,如果你在子类中新增一个函数,然后通过基类进行调用,发现该函数不存在,编译错误。
因此在编译时,函数具体代码区的查找是根据基类指针来的。
当遇到多态时,无非就是告诉调用者,请到具体对象实例中vptr所指向的vtable中所指向的地址去寻找代码,这个过程是运行时完成的。

综上所述,对于我个人而言更加明确了一点,不要在多态的时候去想重载,这是不可能的。
分享到:
评论

相关推荐

    C++多态的实现机制深入理解

    在面试过程中C++的多态实现机制经常会被面试官问道。大家清楚多态到底该如何实现吗?下面小编抽空给大家介绍下多态的实现机制。 1. 用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。 2. 存在虚...

    通过反汇编理解 C++语言实质探讨

    从一 个具体的例子着手,针对VS.NET集成的C++编译器的编译结果,对其进行反汇编,从而揭示出代码后面编译器所作的许多工作,以使读者对类的构造、存 储、数据成员与成员函数之间的联系等有一个较为深入的理解。

    深入理解C++的多态性

    本篇文章是对C++的多态性进行了详细的分析介绍,需要的朋友参考下

    Go语言基础、进阶、提高课程--第八节 深入理解interface1

    答案是否定的,Go 语言引入了一种新类型—Interface,它在效果上实现了类似于 C++的“多态”概念,虽然与 C++的多态在语法上并非完全对等,但至少在最

    深入C++虚表(虚函数 虚表 反汇编)

    多态是C++语言中最重要的特性之一,而虚表以及虚函数是实现多态的重要手段。许多C++语言的教材对于虚函数的使用以及调用机制有着详细的阐述,但是对于虚表的一些细节内容阐述却并不是很深,对于虚表我们可能会有很多...

    现代C++编程:从基础到实战项目全覆盖.docx

    我们将通过理论讲解与实际案例相结合的方式,帮助读者深入理解C++的强大功能。除此之外,教程还包含多个实战项目,如简易的游戏开发、数据结构库的实现和一个小型的数据库系统,旨在通过实践加深对C++编程的理解。...

    程序员在运用C++语言写代码的时候需要注意的五个方面.docx

    程序员在运用C++语言写代码的时候需要...5.对多态的深入理解 - C ++中的多态是一种非常强大的功能,它可以通过虚函数和继承来实现。多态可以使代码更加灵活和可扩展。但是,在使用多态时需要注意多态的实现方式和性能。

    C++编程

    课程名称&gt; 本课程针对C++程序设计和编程思想中...3,深入理解C++语言中类的设计 4,C++中的继承 5,C++项目实战《饮料自动贩卖机—模拟程序》 6,C++中的多态 7,C++中的运算符重载 8,C++模板 9,C++中的输入输出流

    【全新正版】现代C++程序设计(原书第2版)

    本书采用生动轻松的语言,深入阐述了C++语言和面向对象程序设计技术。书中设计了超过115个完整的经过教学测试的代码示例,不仅分析了这些示例的代码片段,而且还解释了如何把它们组成一个完整的程序。此外,各章后面...

    C++入门到精通

    理解C++支持的概念和语言设施 以及编写和执行一个程序所需要的基础知识 读完这部分 内容之后 你应该对 C++语言有了一些认识 但是还谈不上真正理解C++ 这就够了 那是 本书余下部分的目的 第 1 章向我们介绍了语言...

    深入解析ATL(第2版).pdf

    全书内容丰富,深入浅出,主要涵盖了ATL内部架构和实现方法、运用向导简化ATL开发、C++/COM/ATL中字符串的使用技巧、理解并正确实现IUnknown、充分利用ATL提供的Smart Types、撰写能够暴露COM服务器上COM对象的粘合...

    华为新员工C++ 培训试题

    也了解了继承、封装、多态等C++面向对象的基本特征,本课程主要是更进一步探讨一下C++一些基本模型的应用,加深对概念的理解,由于课程时间有限,C++,模型和内容又如此之多,对任何一个模型都无法深入进去,所以...

    C++类型转换的深入总结

    C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。 const_cast,字面上理解就是去const属性。 static_cast,命名上理解是静态类型转换。如int转换成char。 dynamic_cast,命名上理解是动态类型转换。...

    传智播客扫地僧视频讲义源码

    本教程共分为5个部分,第一部分是C语言提高部分,第二部分为C++基础部分,第三部分为C++进阶部分,第四部分为C、C++及数据结构基础部分,第五部分为C_C++与设计模式基础,内容非常详细. 第一部分 C语言提高部分目录...

    asp.net知识库

    如何在Asp.Net1.1中实现页面模板(所谓的MasterPage技术) Tool Tip 示例(FILTER版) Tool Tip示例 (htc版) 一个.net发送HTTP数据实体的类 按键跳转以及按Enter以不同参数提交,及其他感应事件 动态控制Page页的...

    C#微软培训资料

    18.2 在 C #代码中调用 C++和 VB 编写的组件 .240 18.3 版 本 控 制 .249 18.4 代 码 优 化 .252 18.5 小 结 .254 第五部分 附 录 .255 附录 A 关 键 字.255 附录 B 错 误 码.256 附录 C .Net 名字空间...

    精通DirectX.3D图形与动画程序设计.pdf

    5.5 深入理解光照计算模型 5.6 小结 第6章 纹理映射基础 6.1 基本概念 6.2 使用纹理 6.3 纹理过滤方式 6.3.1 最近点采样  6.3.2 线性纹理过滤 6.3.3 各项异性纹理过滤 6.3.4 多级渐进纹理过滤 6.3.5 纹理过滤方式...

Global site tag (gtag.js) - Google Analytics