将指向基础对象的指针转换为派生类的指针

时间:2012-11-21 00:34:12

标签: c++ pointers inheritance

我对将基类对象的指针转换为派生类的指针感到困惑。 请检查以下代码:

derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();

结果是:

  • 我是基地的虚拟功能。
  • 我是派生类中的一个函数。
  • 任何人都可以帮我解释为什么d1->print()打印“我是基础中的虚函数。”?

    #include <iostream>
    using namespace std;
    
    class base
    {
    public:
        virtual void print()
        {
            cout << "I'm a virtual function in base." << endl;
        }
    };
    
    class derivate_class : public  base
    {
    public:
        void print()
        {
            cout << "I rewrite the virtual function in base." << endl;
        }
    
        void print1()
        {   
            cout << "I'm a function in derivate class." << endl;
        }
    };
    
    int main()
    {
        base* b = new base();
        derivate_class *d = new derivate_class();
        b->print();
        d->print1();
        base* cb = b;
        b = d;
        b->print();
        cout << "*********************" << endl;
    
        derivate_class *d1 = (derivate_class*)cb;
        d1->print();
        d1->print1();
    
        system("pause");
        return 0; 
    }
    

    2 个答案:

    答案 0 :(得分:2)

    这是UB,所以任何事情都可能发生。

    但是这里有一个解释:d1实际上并不指向derivate_class,而是指向base

    base* b = new base();
    //...
    base* cb = b;
    derivate_class *d1 = (derivate_class*)cb;
    d1->print();
    d1->print1();
    

    调用是动态解决的,因为它是通过指针而方法是virtual

    print1不是virtual,因此呼叫会静态解决。 print但是virtual,因此调用了派生类型最多的实现。但在这种情况下,派生最多的类型实际上是base

    在幕后,在print中的vfptr指向的虚拟函数表中查找方法cb。由于cvbase,因此该表将是base的表,其中包含具有print实现的函数base::print。这就是为什么这个函数被调用了。

    答案 1 :(得分:0)

    d1是一个derivate_class指针,但它实际指向的数据(cb)是base类型。由于print()是虚拟的,因此动态解析调用,因此它将在虚函数表中找到base的实现而不是derivate_class。