C++ C++;

C++ C++;,c++,inheritance,casting,C++,Inheritance,Casting,我有三个类:Base、Derived(从Base继承)和Stats(使用Base) 程序生成一个派生对象,在程序执行过程中可以多次删除和重构该对象。它还设置一个Stats对象,该对象只创建一次,但需要在派生对象的基础上调用函数。由于可以重构派生对象,因此Stats对象将需要对Base指针的引用,因为指针的值可能会更改。但是,当我在main中构造新的派生对象时,Stats类中的引用看不到新对象 在下面的示例中,d和m_obj都是null,那么当我创建一个新的派生实例时,m_obj仍然是null。这

我有三个类:Base、Derived(从Base继承)和Stats(使用Base)

程序生成一个派生对象,在程序执行过程中可以多次删除和重构该对象。它还设置一个Stats对象,该对象只创建一次,但需要在派生对象的基础上调用函数。由于可以重构派生对象,因此Stats对象将需要对Base指针的引用,因为指针的值可能会更改。但是,当我在main中构造新的派生对象时,Stats类中的引用看不到新对象

在下面的示例中,d和m_obj都是null,那么当我创建一个新的派生实例时,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;
}
#包括
使用名称空间std;
阶级基础{
};
派生类:公共基{
};
typedef Base*const Base_ptr;
班级统计{
公众:
统计(基本*常量和对象):m_对象(对象){

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

您正在创建一个指向
d
指向的临时
Base*
的引用(在本例中为NULL)。在调用构造函数的行完成执行后,该临时命令将被销毁。祝贺您,您刚刚调用了未定义的行为!在此之后,任何事情都可能发生

从本质上讲,如果您展开实际发生的事情,这行内容如下:

Stats s(d);
真的:

{
    Base * const tmp = d;
    Stats s(tmp);
}
当然,
s
不会像本例中那样消失


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

这就是问题所在。为了解决这个问题,我对Stats构造函数进行了模板化,该构造函数进行了C样式转换,因此调用方不必担心这些问题。