2010-10-22 58 views
5

是可能的未初始化的对象传递给父类像在下面的例子中引用初始化的对象iniside构造

class C 
{ 
    public: 
     C(int i): 
      m_i(i) 
     {}; 

     int m_i; 
} 

class T 
{ 
    public: 
     T(C & c): 
      m_c(c) 
     { 
     }; 

     C & m_c; 
}; 


class ST : public T 
{ 
    public: 
     ST(): 
      T(m_ci), 
      m_ci(999) 
     { 
     }; 

     C m_ci; 
}; 

class T构造,c是未初始化的对象的引用。如果class T在施工期间使用了c对象,则可能会导致错误。但由于不是,这个编译和工作正常。我的问题是 - 它制动了某种范例还是好的设计指令?如果是这样,有什么选择,因为我发现分配父类在子类中所需的对象是有用的。

在附注中,我想知道为什么不能更改初始化顺序,以便在初始化某些成员之后调用基类构造函数。

回答

2

可以 ,但你得到未定义的行为。

在Boost的实用程序中,您会发现由R. Samuel Klatchko创建的base-from-member idiom。基本上,你在私人会员的地方建立私人基地。此基地首先被初始化,您可以将其用于其他基地:

// ... 

class C_base 
{ 
public: 
    C_base(int i) : 
    m_ci(i) 
    {} 

    C m_ci; 
}; 


class ST : 
    private C_base 
    public T 
{ 
    public: 
     ST() : 
      C_base(999), 
      T(m_ci), 
     { 
     }; 
}; 

Boost的实用程序消除了重复的代码。

2

我见过很多,许多编译器会发出警告。如果T构造函数不解除引用c引用,那就没问题。

如果你不想要警告,你需要做两个阶段的建设。做一个受保护的Init(C&)方法T,然后调用它在ST构造函数体 - 不幸的是m_c将需要一个指针来做到这一点(因为引用不能被重新分配给另一个对象)

2

将参考或指针传递给未初始化的东西在技术上完全正常。

但是你问的原因可能是你认为某件事很容易出错,通过一些调用链可能会在初始化之前无意中访问该对象。我认为这是一个值得关注的问题。还有一件事是可以去错了,即代码在基类T现在可能通过直接改变ST实例的数据成员无效的ST类不变...

所以,我认为这是一个有点冒险。

关于初始化顺序,C++基于从层次结构中的部分构建的思想。如果构造函数抛出,那么完全构造的东西会自动被破坏。随着更多武断的施工顺序,这将变得更困难或效率更低。

Cheers & hth。,