您可能需要使用可空類型一樣的boost ::可選。這看起來像:
class B {
public:
B()
{
/*
* Here, a has been default constructed and is empty
* You can do computations here and then...
*/
if(/* some elaborate condition*/) {
a = A();
/* access *a from here on */
} else {
/* anything you want */
}
}
private:
boost::optional<A> a;
};
這回答這個問題,但我認爲,如果你告訴你真正想實現一個更合適的答案可以給予。我覺得這更像是一個設計問題,而不是語言問題。擴展的想法如下。
在上面的'解決方案'中,else
子句中出現了什麼?由於A
顯然只能是默認構造的,所以不像你可以放置不同的構造函數調用。如果您不初始化a
,則會引入(圈)複雜度,因爲這意味着每個方法都必須檢查a
是否處於活動狀態。或者你可以扔;然而,我會重構在函數中執行檢查(或其他)的代碼;一個私人靜態方法或如下所示的匿名/靜態獨立功能:
namespace {
A
prepare_A()
{
/* elaborate computations, possibly throw */
return A();
/*
* if A had different constructors we could also conditionally
* return an A(0) or whatever.
*/
}
} // namespace
B::B()
:
a(prepare_A())
{
/*
* a is of type A, not boost::optional<A>
*/
}
然而,這假設是A
能夠複製。如果情況並非如此,或者複製A
是不可接受的,我會認爲第一種解決方案是可接受的,因爲作爲類不變量a
的一部分永遠不會爲空。
如果我們知道A
和B
之間的關係,推薦一些東西會更容易。如果你想有條件地初始化它,你爲什麼要把A
成員放入B
?或許兩者之間的關係,首選應該不會聚集,但聯想:一個指針成員(或引用成員,如果你小心賦值運算符),以A
如:
class B {
public:
explicit
B(A& a_)
/*
* Important: not A const&,
* we only want lvalues.
* Contract on the caller: a must remain valid during
* the lifetime of *this.
*/
:
a(&a_)
{
/*
* class invariants: a != 0,
* *a remains valid for the lifetime of B
*/
}
private:
A* a;
};
這樣,你不會引入圈複雜度而且你不在乎A和A何時構建。合同爲調用者增加了一點負擔,但由於我們只能將左值傳遞給構造函數,所以很難(呃)濫用。
這個問題太含糊。情況如何?就其本身而言:只需使用指針即可。 – 2011-04-27 15:05:25
如果您不想創建類的實例,請不要編寫用於創建類實例的代碼。 – 2011-04-27 15:06:01
您可以將默認構造函數定義爲private。看看C++中的Singleton模式,看看如何做到這一點。 – Kieveli 2011-04-27 15:34:43