【发布时间】:2015-05-28 23:58:59
【问题描述】:
我需要从 Base 类派生一个 Child 类,满足以下要求:
- Class Base 构造函数接受对 Foo 类对象的引用。
- Foo 类的对象应该与 Child 类的对象具有相同的生命周期。
- Foo、Child 和 Base 的构造函数可以抛出,代码应充分破坏到目前为止创建的内容。
- 代码是多线程的,可以同时调用多个child的构造函数
- Foo 没有复制构造函数,没有默认构造函数。
(与How to remind a param passed to the base class constructor?有一些相似之处 但是在上述问题中几乎没有讨论异常安全性)
在实现的过程中,遇到了以下困难:
A.让 Foo 类的对象成为 Child 的成员似乎很自然
class Base {
public:
Base(Foo& foo);
};
class Child: public Base {
public:
Child(int par);
private:
Foo m_foo;
};
但是,我现在如何在 Child 构造函数中初始化它?
Child::Child(int par):
Base(Foo(par)),
m_Foo(par) ...
这会将 ref 传递给临时类 Base Constructor(它甚至会编译吗?),然后单独初始化 m_Foo。这很糟糕。
如果不是满足 #4 和 #5 的要求,我可以在调用 Base 时使用静态方法共同构造 Foo,然后将其传递给 m_Foo:
Foo Child::s_Helper(int par) {
if (!s_FooConstructed) {
s_Foo = Foo(par);
s_FooConstructed = true;
}
return s_Foo;
}
我希望使用 unique_ptr 或 shared_ptr 作为 Child 类成员:
class Child: public Base {
public:
Child(int par);
private:
unique_ptr<Foo> m_Foo;
bool m_IsFooConstructed;
unique_ptr<Foo> x_FooHelper(int par);
};
Child::Child(int par):
Base(x_FooHelper(par)),
m_Foo(x_FooHelper(par))
{}
unique_ptr <Foo> Child::x_FooHelper(int par)
{
if(!m_FooConstructed) {
m_Foo.reset(new Foo(par)); ///< Problem here
m_FooConstructed = true;
}
return m_Foo;
}
然而,这里 m_Foo 不是在调用 x_FooHelper 时构造的... 与 shared_ptr 相同
我可以创建一个指针:
class Child: public Base {
public:
Child(int par);
private:
Foo* m_Foo;
bool m_IsFooConstructed;
Foo* x_FooHelper(int par);
};
Child::Child(int par):
Base(*x_FooHelper(par)),
m_Foo(x_FooHelper(par))
{}
Foo* Child::x_FooHelper(int par)
{
if(!m_FooConstructed) {
m_Foo = new Foo(par);
m_FooConstructed = true;
}
return m_Foo;
}
但是在这里,如果 Base 构造函数抛出,Foo 已经创建,并且它不会被销毁,因为它由原始指针 (m_Foo) 保存~Child 也不会被调用。我能做什么?
【问题讨论】:
标签: c++ constructor