【问题标题】:converting pointer to base object into pointer of derivate class将指向基对象的指针转换为派生类的指针
【发布时间】:2012-11-21 00:34:11
【问题描述】:

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

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

结果是:

  • 我是base中的一个虚函数。
  • 我是派生类中的一个函数。
  • 谁能帮我解释一下为什么d1->print()会打印“我是base中的一个虚函数。”?

    #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——任何事情都有可能发生。切换到 dynamic_cast&lt;&gt; 而不是 C 风格的强制转换并检查 nullptr。
    • @ildjarn,非常感谢您的回复。我正在阅读 STL 的源代码。在链表的 STL 中,它有一些代码将指向基对象的指针转换为派生类的指针。所以我在问题中编写代码来测试如果将指向基对象的指针转换为派生类的指针会发生什么。我真正的问题是我们什么时候需要将指向基对象的指针转换为派生类的指针?我将在下面发布 STL 代码。
    • @ildjarn,我开始一个新问题:stackoverflow.com/questions/13486010/…

    标签: c++ pointers inheritance


    【解决方案1】:

    这是 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

    在底层,方法printcb 中的vfptr 指向的虚函数表中查找。由于cvbase,因此该表将是base 的表,其中包含函数printbase::print 实现。这就是函数被调用的原因。

    【讨论】:

    • 非常感谢您的回复。我正在阅读 STL 的源代码。在链表的 STL 中,它有一些代码将指向基对象的指针转换为派生类的指针。所以我在问题中编写代码来测试如果将指向基对象的指针转换为派生类的指针会发生什么。我真正的问题是我们什么时候需要将指向基对象的指针转换为派生类的指针?我将在下面发布 STL 代码。
    • 我开始一个新问题:stackoverflow.com/questions/13486010/…
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-10
      • 2014-06-16
      • 1970-01-01
      相关资源
      最近更新 更多