拥有一个成员并将其传递给基类,如果:
DerrivedClass::DerrivedClass(SomeParamType* p)
: BaseClass(p),
derrivedClassMember(p),
{
...
}
...但是如何在不将它作为参数传递给DerrivedClass构造函数的情况下进行共享?这有效吗?或者derrivedClassMember目前尚未初始化?
DerrivedClass::DerrivedClass()
: BaseClass(derrivedClassMember),
derrivedClassMember(new SomeParamType()),
{
...
}
我无法更改基类实现。
答案 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