如何提醒传递给基类构造函数的参数?

时间:2013-09-05 08:49:44

标签: c++ constructor

拥有一个成员并将其传递给基类,如果:

DerrivedClass::DerrivedClass(SomeParamType* p)
    : BaseClass(p),
      derrivedClassMember(p),
{
 ...
}

...但是如何在不将它作为参数传递给DerrivedClass构造函数的情况下进行共享?这有效吗?或者derrivedClassMember目前尚未初始化?

DerrivedClass::DerrivedClass()
    : BaseClass(derrivedClassMember),
      derrivedClassMember(new SomeParamType()),
{
 ...
}

我无法更改基类实现。

5 个答案:

答案 0 :(得分:4)

在C ++ 11中,您可以使用委托构造函数:

class Derived : public Base {
public:
    Derived() : Derived(new SomeParamType()) {}
    ...
private:
    Derived(SomeParamType* p) : Base(p), derivedMember(p) {}
};

作为旁注,我知道这可能只是一个例子,但你不应该在构造函数中像这样在堆上创建非托管对象:如果Base构造函数抛出那么你就是为了一个内存泄漏。尽可能选择智能指针。

答案 1 :(得分:3)

我在写这篇文章的时候正在畏缩,但是......

DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
    : BaseClass(p),
      derrivedClassMember(p)
{
}

我现在需要洗澡。无论如何,根据您的问题,是的,您的基础构造函数应该在您的成员初始化之前执行。成员必须以自上而下的顺序进行初始化,从构造函数中的基本成员开始并进行处理。

注意:我必须清除我的标准副本才能找到指定的位置,但我很确定它在那里,因为lint 喜欢告诉你的不合适之处订购初始化警告及其不合规情况。

答案 2 :(得分:2)

当时没有初始化。在初始化derrivedClassMember之前调用基类构造函数。这是因为派生类的派生成员或构造函数可能依赖于基类的成员。

答案 3 :(得分:2)

总结到目前为止给出的答案,并添加一些,有一些可能的解决方案。

1 如果您的基类具有该成员的访问者,则相当容易:

DerrivedClass::DerrivedClass()
: BaseClass(new SomeParamType()),
  derrivedClassMember(getBaseClassMember()),
{
  ...
}
在C ++ 11中

2 ,使用委托构造函数,调用您发布的原始构造函数:

DerrivedClass::DerrivedClass()
: DerrivedClass(new SomeParamType())
{}
C ++ 03中的

3 ,使用默认参数(这很难看):

DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
    : BaseClass(p),
      derrivedClassMember(p),
{
 ...
}

4 为了摆脱C ++ 03中的构造函数默认参数,另一种解决方法是使用多重继承来在基类之前初始化derivedclassMember

struct DerivedClassInitializationWorkaround {
  SomeParamType* derivedClassMember:
  DerivedClassInitializationWorkaround(SomeParamType* param) 
    : derivedClassMember(param) {}
};

class DerivedClass : private DerivedClassInitializationWorkaround, //this has to go first!
                     public BaseClass {
public:
  DerivedClass::DerivedClass()
    : DerivedClassInitializationWorkaround(new SomeParamType())
    , BaseClass(derivedClassMember)
  {}
};

基类的初始化按其声明的顺序进行,因此如果您从DerivedClassInitializationWorkaround派生,则它包含的derivedClassMember首先被初始化。

在任何情况下,您的代码都不是异常安全的。您不应该将拥有指针存储为原始指针,而是使用智能指针。由于您无法更改基类,因此您必须确定它是否取得对象的所有权(即,它是否会破坏传递给其构造函数的对象。

如果基类对象取得所有权,那么你或多或少地坚持使用现有的解决方案,除了你的派生类应该存储一个引用而不是指针,因为基类对象和其他SomeParamType对象将比派生类'对象更长。

如果基类没有获得所有权,则应存储unique_ptr

class DerivedClass : public BaseClass {
  unique_ptr<SomeParamType> derivedClassMember;

  DerivedClass::DerivedClass(unique_ptr<SomeParamType> param)
    : BaseClass(param.get())
    , derivedClassMember(move(param))
  {}

public:
  DerivedClass::DerivedClass()
    : DerivedClass(make_unique<SomeParamType>)
  {}
};

答案 4 :(得分:1)

简短回答是否定的,无效。

这是你问题的一个很好的答案:

Order of calling base class constructor from derived class initialization list