2014-02-18 65 views
0

我想構造沒有默認構造函數的類成員。 基本上我想做的事情在類的構造函數如下:有條件地構造不帶默認構造函數的成員對象

class X{ 
public: 
    X(Config config) { 
     if (config.getBool) memberA("yes"); 
     else memberA("no"); 
    } 
} 

的問題是,因爲之前說沒有爲類memberA沒有默認構造函數,因此編譯器不能構建它造成的錯誤。 很顯然,我可以這樣做:

class X{ 
public: 
    X(Config config) : memberA("yes") { 
    if (!config.getBool) memberA = MemberAClass("no"); 
    } 
} 

,但我不知道是否有一種方法來構造成員,如果條款,但沒有以防止在類的靜態成員的副作用調用構造兩次使用。

更新:我忘了提,我真的需要兩個參數,但原則反正工作:

X::X(Config cfg):member(cfg.getBool()?"yes":"no",cfg.getBool()?1:2){}; 
+8

'級X :: X(配置):memberA(配置。 getBool?「yes」:「no」){}'? – Casey

+3

@Casey這應該是一個答案。 – juanchopanza

+0

是的,這基本上是伎倆,謝謝:) – Marste

回答

4

你必須使用構造函數初始化列表和有條件的經營者(而不是if)如下:

X::X(const Config& config) : memberA(config.getBool() ? "yes" : "no") 
{} 

或創建一個函數來計算正確的說法:

const char* compute_memberA_arg(const Config& config) { 
    if (config.getBool()) { return "yes"; } 
    else { return "no"; } 
} 

X::X(const Config& config) : memberA(compute_memberA_arg(config)) 
{} 
0

這是C++的主要缺陷之一,即不能將構造的構造嵌入到構造函數代碼中。當你需要根據參數使用不同的構造函數時,這是特別討厭的。在這些情況下,最好的解決方法是將您的成員初始化(部分)移動到init()函數中。然後,你可以做這樣的事情:

class Foo { 
    Bar bar; 
public: 
    Foo(bool flag) { 
     if(flag) { 
      bar.init("init from string"); 
     } else { 
      bar.init(3, 7, 5); 
     } 
    } 
}; 
+1

相反,它是C++社區的主要缺陷之一,許多程序員不知道如何去做。不要使用'init'函數。 –

+0

@LightnessRacesinOrbit我同意:如果你不能處理'init()'函數,你不應該使用它。但是,當出現需要'init()'函數的情況時,你必須承認失敗。並且存在這些情況。更好地確保,你*可以*處理它們。 – cmaster

+0

@cmaster:我從來沒有見過這樣的情況,這又是'init'函數放錯位置的情況。正如賈羅德和凱西所表明的那樣,實際上有多種更好的選擇。 – MSalters

1

鑑於更新,我建議一個(靜態)輔助方法:

MemberType X::initMemberA(bool flag) { 
    return flag ? MemberType("yes", 1) : MemberType("no", 2); 
} 
X::X(Config cfg) : memberA(initMemberA(cfg.getBool())) { }