2017-04-25 53 views
3

我有一個具有GUI成員變量的類。我必須在施工時提供文字,字體和大小。不幸的是,擁有類的構造函數沒有得到這些數據,但必須從工廠(特別是字體)獲取。成員變量的新放置位置

class Element { 
public: 
    Element(); 
    /* other stuff */ 

private: 
    UIElement uie; 
}; 

Element::Element() /* cannot construct the object here */ { 
    /* ... some aquiring ... */ 
    new (&uie) UIElement(/* now I have the required data */); 
} 

這是一個有效的實施?我是否可以簡單地將物體放置到已建造Element課程的空間中?

+1

只需使用作業。你的編譯器會優化副本。 – Qix

+0

這看起來不正確的C++代碼 - 你正在新建一個堆棧變量。 –

+1

至少,您需要調用現有的'Element'對象的析構函數。但是這對我來說似乎是很糟糕的設計。爲什麼不只是用'Element'的兩階段施工設計?或者,如果失敗了,則爲成員變量分配一個新的'Element'對象,並讓優化器處理它。 –

回答

2

您在代碼/* cannot construct the object here */中發表評論,但事實是在輸入複合語句之前構造的成員

這是一個有效的實施?我可以簡單地將對象放入已經由構造Element類分配的空間中嗎?

否。在您可以使用放置新功能之前,必須首先銷燬默認的構造成員 - 除非該成員可以被破壞。

然而,這是毫無意義的。無論你在複合語句中可以做什麼,你也可以在初始化列表中執行。如果一個表達式不夠用,那麼你可以簡單地寫一個單獨的函數,然後調用它。

UIElement init_uie(); // could be a member if needed 
Element::Element() : uie(init_uie()) { 
1

一種選擇是分解出的初始化代碼:

Element::Element() : uie(get_uie()) {} 

UIElement get_uie(){ 
    /* ... some aquiring ... */ 
    return UIElement(/* now I have the required data */); 
} 

你也可以做它內嵌沒有這樣的額外功能,但它無疑是難以閱讀:

Element::Element() : uie(
    []{ 
     /* ... some aquiring ... */ 
     return UIElement(/* now I have the required data */); 
    }() 
){}