奇怪的转换问题在C ++中派生到Base

时间:2011-03-15 20:33:04

标签: c++ inheritance casting

我有三个类:Base,Derived(继承自Base)和Stats(使用Base)。

程序生成一个Derived对象,在程序执行期间可以删除和重建几次。它还设置一个Stats对象,该对象只会被创建一次,但需要在Derived对象的Base上调用函数。因为可以重建Derived对象,所以Stats对象将需要对Base的指针的引用,因为指针的值可能会改变。但是,当我在main中构造一个新的Derived时,Stats类中的引用不会看到新对象。

在下面的示例中,d和m_obj都为null,然后当我创建一个新的Derived实例时,m_obj仍为null。这对我来说没有意义。令人困惑的是,如果我将行Derived* d = 0;更改为Base* d = 0;,它就可以正常工作。有什么想法吗?

#include <iostream>
using namespace std;

class Base {
};

class Derived : public Base {
};

typedef Base* const base_ptr;

class Stats {
public:
    Stats(Base * const &obj) : m_obj(obj) {
        cout << "In Stats():" << endl;
        cout << "   m_obj = " << m_obj << endl;
    }

    void f() const {
        cout << "In f:" << endl;
        cout << "   m_obj = " << m_obj << endl;
    }

private:
    base_ptr &m_obj;
};

int main() {
    Derived* d = 0;
    cout << "d = " << d << endl;

    Stats s(d);

    d = new Derived();
    cout << "d (after new) = " << d << endl;

    s.f();

    return 0;
}

2 个答案:

答案 0 :(得分:3)

您的Stats实际上是d值的临时副本。这是因为d不属于Base * const &类型(但可以转换为)。

答案 1 :(得分:3)

您正在创建对临时Base *的引用,该引用指向d指向的内容(在本例中为NULL)。在调用构造函数的行完成执行后,该临时文件被销毁。恭喜,您刚刚调用了未定义的行为!在那之后,任何事情都可能发生。

基本上,如果你扩展出真正发生的事情,这一行就是这样的:

Stats s(d);

确实

{
    Base * const tmp = d;
    Stats s(tmp);
}

当然,s不会像在这个例子中那样消失。

d的类型为Base *时,编译器不必进行任何类型转换,因此不必创建任何临时值。