使用不同的构造函数重新分配对象

Posted

技术标签:

【中文标题】使用不同的构造函数重新分配对象【英文标题】:Reassign object with different constructor 【发布时间】:2014-06-30 07:17:23 【问题描述】:

MyClass班级,我有一个成员Dialog dialog_

调用MyClass的构造函数后,我想用MyClass的构造函数中创建的参数为dialog_调用不同的构造函数(这就是为什么我不能直接为@调用不同的构造函数987654327@,但只是默认的)。

所以我尝试了

dialog_ = Dialog(/* different constr. w/ parameters passed from MyClass */);

但这不起作用。错误是

Error: no operator "=" matches these operands
operand types are: Dialog = Dialog

于是我google了一下,在this SO thread (3rd answer)找到了一个我试过的代码sn-p:

dialog_.~Dialog();
new(&dialog_) Dialog(/* different constr. w/ parameters passed from MyClass */);

而且它有效。线程中的答案虽然指出“这个的价值并没有超出纯粹的理论范围。不要在实践中这样做。整个事情很难描述。

那么在不使用明显不受欢迎的代码的情况下,我能做些什么来解决我的问题呢?

我希望你能理解我想要达到的目标。谢谢!

【问题讨论】:

顺便说一句,析构函数后跟构造函数是邪恶的。不要这样做。永远。 是的,sn-p 太可怕了。我建议使用某种形式的“assign”/“reassign”方法组合,而不是依赖构造函数。 @RichardHodges 不,我没有使用 C++11。而且我知道这很糟糕,这就是我在这里问的原因,但我缺乏自己解决问题的专业知识^^ 在这种情况下,要么使用我的答案中的选项 1,要么看看你是否可以重构你的类设计,以便它封装你可以在初始化列表中构造的更小的类。 【参考方案1】:

有两种方法可以实现您想要的。

在 c++98 中,您需要将一些初始化推迟到您从构造函数调用的 init() 函数。这有点棘手,因为这意味着您的许多成员变量的重复构造和赋值。

在 c++11 中,您可以在初始化器列表中调用 1 个其他构造函数,传递计算值(这些值可以在静态函数中计算以保持整洁)。

如果您提供构造函数代码示例,我可以向您展示如何操作。

【讨论】:

听起来他想延迟成员的初始化。我会为此建议boost::optional 我不知道我们是否在谈论相同的init() 函数,但我之前尝试过。该函数具有与第二个构造函数相同的参数,但与我原来的帖子中的错误相同,除了 Dialog 被另一个作为参数的类替换......我将在下面的另一条评论中解释它: Dialog 的两个构造函数是Dialog()Dialog(DialogType_ type, Resources &resources)DialogType_ 只是 Dialog 类中的一个枚举。所以默认构造函数Dialog()只是空的,而另一个构造函数将type_初始化为typeresources_初始化为resources(都是成员变量)。 我使用函数init(DialogType_ type, Resources &resources)时遇到的错误是关于Resources。它看起来像这样:void Dialog::initialise(DialogType_ type, Resources &resources) type_ = type; resources_ = resources;。错误在resources_ = resources 行。我希望我能解释一下:/【参考方案2】:

您可以将 Dialog 成员放在 std::unique_ptr 中,然后在需要时替换它:

class MyClass 
private:
    std::unique_ptr<Dialog> dialog_;

public:
    MyClass():
        dialog_( /* ... first constructor ... */ ) 
    void setNewDialog(/* parameters */) 
        dialog_.reset(new Dialog(/* parameters */) );
    
;

【讨论】:

我从未与std::unique_ptr 合作过,但这听起来是一个不错且简单的想法。如果我使用您的示例,我需要处理new 还是它会自动管理内存? std::unique_ptr 拥有该对象并在其析构函数中释放它。但请记住,如果您希望您的类可复制,则必须编写一个复制构造函数。【参考方案3】:

我试过的都没有用,所以我就用吧

dialog_.~Dialog();
new(&dialog_) Dialog(/* ... */);

虽然不好

【讨论】:

unique_ptr 解决方案有什么问题?上面的代码属于非常糟糕的黑客级别,只有在你完全知道自己在做什么的情况下才应该使用。 参见***.com/questions/14187006/…:“然而,在一个相当低的级别上管理内存,就像上面显式调用析构函数一样,是糟糕设计的标志。可能,它实际上不仅是糟糕的设计,而且是完全错误的” 我尝试使用 std::unique_ptr 但它在我现有的代码中引入了很多新错误(因为我正在绘制对话框等)。明天当我的挫败感减弱时,我会再次尝试这种方法:P

以上是关于使用不同的构造函数重新分配对象的主要内容,如果未能解决你的问题,请参考以下文章

拷贝构造函数和赋值运算符的认识

基类和派生类构造函数的内存分配

类方法详解

C++的构造函数的作用:初始化类对象的数据成员

C++的构造函数的作用:初始化类对象的数据成员

C++的构造函数的作用:初始化类对象的数据成员