【问题标题】:How to initialize member object when parameters aren't available at time of initializer list?当初始化列表时参数不可用时如何初始化成员对象?
【发布时间】:2018-08-07 01:05:18
【问题描述】:

目前的结构类似于

class B {
  //no default constructor
  //this is a class in a third-party library, can't be modified
  B(Lots ofData, AndOther arguments);
}

class A {
  B b;

  A(some_parameters){
     //Do a lot of stuff with those parameters, make Results
     B b(Results, Results); //ERROR
  }
}

所以,我需要在B 上调用构造函数,但我没有足够早的信息在初始化列表中执行此操作。以后如何在B 上调用构造函数?因为B 没有简单的构造函数,所以我不能用一些愚蠢的默认值完全初始化并在以后覆盖它。

我无法更改 B 类。

【问题讨论】:

  • 你遇到了什么编译错误?
  • @Bill 上面的代码(几乎)可以编译,但它声明了两次b。我试图说明我想做什么(如果它没有重新声明它)。它实际上并没有编译,因为B 没有默认构造函数。

标签: c++ class constructor initialization


【解决方案1】:

如果B 有一个复制/移动构造函数,您可以简单地创建一个返回B 的函数并使用它来初始化成员,如下所示:

B makeB(some_parameters) {
    //Do a lot of stuff with those parameters, make Results
    return B(Results, Results);
}

class A {
    B b;

    A(some_parameters)
      : b(makeB(some_parameters))
    {
    }
};

如果无法将B 复制/移动到您的成员中,那么一个简单的解决方案就是动态分配B 对象。这样你就可以将所有“很多东西,制作结果”移动到一个函数中

#include <memory>

std::unique_ptr<B> makeB(some_parameters) {
    //Do a lot of stuff with those parameters, make Results
    return std::make_unique<B>(Results, Results);
}

class A {
    std::unique_ptr<B> b;

    A(some_parameters)
      : b(makeB(some_parameters))
    {
    }
};

如果您希望您的 B 直接存在于 A 对象中,您可以使用 std::optional&lt;B&gt; 或未命名的联合,以便稍后在其中放置对象:

#include <memory>

class A {
    union {
        B b;
    };

    A(some_parameters) {
        //Do a lot of stuff with those parameters, make Results
        new (&b) B(Results, Results);
    }

    ~A() {  // this is only needed if B has a non-trivial destructor
        b.~B();
    }
};

【讨论】:

  • 为什么您的第一个解决方案需要动态内存? makeB 不能返回 B,而不是 unique_ptr&lt;B&gt;,并且仍然按照所示初始化成员 b
  • 是的,假设 B 有一个复制/移动构造函数,它可以。我认为它没有这些,因为我希望该解决方案如此明显以至于无需提出问题……但为了完整起见,它可能应该添加到答案中……
【解决方案2】:

C++11 中的另一种选择是委托构造函数,类似于:

Result foo(Parameters some_parameters)
{
    //Do a lot of stuff with those parameters, make Results
}

class A
{
    B b;
public:    
    A(Parameters some_parameters) : A(foo(some_parameters)){}

private:
    A(Result result) : b(Results, Results) {}
};

【讨论】:

    猜你喜欢
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 2015-04-27
    • 2011-07-14
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多