[英]Construct an object, pass it to the base class constructor keeping control of its lifetime
我需要從Base類派生一個Child類,並具有以下要求:
(與如何提醒傳遞給基類構造函數的參數有些相似之處;但是在上述問題中幾乎沒有討論異常安全性)
在實施它時,我遇到了以下困難:
答:讓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構造函數(它甚至可以編譯嗎?),然后分別初始化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;
}
但是,這里在調用x_FooHelper時未構造m_Foo ...與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也不會被調用。 我能做什么?
使用Base-from-Member成語 -創建另一個擁有Foo
類作為Child
的第一個基礎:
class Base {
public:
Base(Foo& foo);
};
struct FooOwner {
FooOwner(int par)
: m_foo(par)
{ }
Foo m_foo;
};
class Child
: private FooOwner // first, so Foo is initialized
, public Base // before Base
{
public:
Child(int par)
: FooOwner(par)
, Base(FooOwner::m_foo)
{
/* something else */
}
};
Foo
的生命周期仍然與Child
,您可以放心地將它的引用傳遞給Base
因為它肯定是在Base
之前構造的。
如果由於某種原因而覺得太冗長,也可以使用boost::base_from_member
實現相同的目的:
class Child
: private boost::base_from_member<Foo>
, public Base
{
typedef boost::base_from_member<Foo> FooOwner;
Child(int par)
: FooOwner(par)
, Base(FooOwner::member)
{ }
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.