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

converting pointer to base object into pointer of derivate class

本文关键字:指针 派生 转换 对象      更新时间:2023-10-16

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

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; 
    }
    

    它是 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因此调用是静态解析的。 然而printvirtual的,所以最派生类型的实现被调用。但在这种情况下,派生最多的类型实际上是base

    在引擎盖下,在 vfptr cb指向的虚函数表中查找方法print。由于cv是一个base,该表将是base的表,其中包含与base::print实现print的函数。这就是调用函数的原因。

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