深入理解C++中多态的实现_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > 深入理解C++中多态的实现

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

 2010/12/23 8:03:24  tinggo  http://tinggo.javaeye.com  我要评论(0)
  • 摘要:对于C++中多态性是面向对象中很重要的特性之一,每种面向对象的语言对于多态的实现都不尽相同。最近,学习中发现一段既陌生又熟悉的代码,大致情况如下#include#include<iostream>usingnamespacestd;classBaseClass{public:virtualvoidDisplay(){cout<<"BaseClass::Display()"<<endl;}virtualvoidDisplay(inta){cout<<
  • 标签:实现 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中所指向的地址去寻找代码,这个过程是运行时完成的。

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