[英]Is there a way to late-initialize a member variable (a class) in C++?
我來自Java背景。 我有以下程序。
#include <string>
#include <iostream>
class First {
public:
First(int someVal): a(someVal) {
}
int a;
};
class Second {
public:
First first;
Second() { // The other option would be to add default value as ": first(0)"
first = First(123);
}
};
int main()
{
Second second;
std::cout << "hello" << second.first.a << std::endl;
}
在課堂Second
,我想變first
保持未初始化,直到我特別是在初始化Second()'s constructor
。 有辦法嗎? 或者我只剩下2個選項?:
我不能初始化first
在初始化列表與正確的價值,因為一些操作后得到的值。 因此, first
的實際所需值僅在Second()
構造函數中可用。
我的建議:使用功能:
private: static int calculate_first(int input) {return input*5;}
explicit Second(int input) : first(calculate_first(input)) {}
基類將按照它們在類繼承列表中聲明的順序進行初始化,然后成員將按照它們在類中列出的順序進行初始化,因此計算可以依賴於非靜態成員變量和基數如果已經初始化了類。
默認構造函數,然后重新分配:
explicit Second(int input) : first(0) { first = input*5; }
虛擬價值,然后重新分配:
boost::optional<First> first;
explicit Second(int input) { first = input*5; }
使用boost :: optional:
std::unique_ptr<First> first;
explicit Second(int input) { first.reset(new First(input*5));}
Second(const Second& r) first(new First(*(r->first))) {}
Second& operator=(const Second& r) {first.reset(new First(*(r->first)));}
使用堆:
This is tricky and not suggested
and worse in every way than boost::optional
So sample deliberately missing.
But it is an option.
新位置:
This is tricky and not suggested and worse in every way than boost::optional So sample deliberately missing. But it is an option.
first
在成員初始化列表中初始化。
在輔助函數中執行計算並使用轉發構造函數可能會有所幫助:
class Second {
public:
Second() : Second(helper_function()) {}
private:
Second(int calc): first(calc) {}
static int helper_function() { return ...; }
First first;
};
你可以在評論中做你所說的,或者,你可以先做一個指向First的指針並隨時給它內存,雖然我不推薦這種方式
分離對象生存期的一種方法是使用堆, first
一個指針並在任何時候初始化它:
class Second {
public:
First* first;
Second() {
first = new First(123);
}
};
當然,你可能想要使用某種智能指針而不是原始指針。
這句話是問題的核心:
我無法在初始化列表中首先使用正確的值初始化,因為該值是在某些操作之后獲得的。
你應該知道你想要做的事情也不是Java中完美的編程風格 。 保留具有某個默認值的字段,然后在完成某些計算后稍后分配它有效地防止它成為final
,從而使類不可變。
在任何情況下,您的目標必須是使用私有幫助函數 (可能是靜態的)將這些計算直接推送到成員的初始化中:
class Second {
private:
First first;
static int getInitializationData()
{
// complicated calculations go here...
return result_of_calculations;
}
public:
Second() : first(getInitializationData()) {}
};
在我看來,其他一切只是一種解決方法,從長遠來看會使你的生活復雜化。
如果您不編寫顯式初始化成員變量的代碼,則使用默認初始值設定項對其進行初始化。
C ++標准草案具有以下關於基類和成員變量的初始化:
12.6初始化[class.init]
1如果沒有為(可能是cv限定的)類類型(或其數組)的對象指定初始化程序,或初始化程序具有表單(),則按8.5中的指定初始化對象。
和
12.6.1顯式初始化[class.expl.init]
1可以使用帶括號的表達式列表初始化類類型的對象,其中表達式列表被解釋為被調用以初始化對象的構造函數的參數列表。 或者,可以使用=初始化形式將單個賦值表達式指定為初始化程序。 直接初始化語義或復制初始化語義都適用; 見8.5。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.