2017-04-25 58 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 */); 
    }() 
){}