简体   繁体   English

如何正确初始化非默认可构造的类成员?

[英]How to properly initialize non-default-constructible class member?

Assume I define a class Foo , which does not implement a default constructor. 假设我定义了一个类Foo ,它没有实现默认的构造函数。 In addition, I have a class Bar , which "owns" an instance of Foo : 另外,我有一个类Bar ,它“拥有”一个Foo实例:

class Foo() {
  private:
    int m_member;
  public:
    Foo( int value ) : m_member(value) { }
};

class Bar() {
  private:
    Foo m_foo;
  public:
    Bar( /* ... */ ) {
      int something;
      /* lots of code to determine 'something' */
      /* should initialize m_foo to 'Foo(something)' here */
    }
};

The code as shown won't run, since Bar is trying to call the default constructor of Foo . 由于Bar试图调用Foo的默认构造函数,因此显示的代码将无法运行。

Now what I am trying to do is to have the constructor of Bar first determine something and then pass the result to the constructor of Foo . 现在我要做的是让Bar的构造函数首先确定something ,然后将结果传递给Foo的构造函数。

One way to solve this is to have Bar only own a reference/pointer to Foo and initialize it after m_something was determined. 解决这个问题的一种方法是让Bar只拥有一个指向Foo的引用/指针,并在确定m_something之后初始化它。 However, I'd like to avoid that to make clear that the lifetime of m_foo is completely dependent on the lifetime of the owning class. 但是,我想避免这一点,以明确m_foo的生命周期完全取决于拥有类的生命周期。

Another way would be to implement a default constructor in Foo and set the value later, which I would also like to avoid, since any instance of Foo should have a valid value for it's member (at any time). 另一种方法是在Foo实现默认构造函数并稍后设置该值,我也想避免使用,因为任何Foo实例都应该为其成员提供有效值(在任何时候)。

What is the proper way to implement this? 实现这个的正确方法是什么? Am I stuck with a reference/pointer here? 我在这里坚持使用参考/指针吗?

The best idea will be to create helper function, that will calculate something and then just initialize m_foo in constructor initialized list. 最好的想法是创建辅助函数,它将计算一些东西,然后在构造函数初始化列表中初始化m_foo

class Bar {
  private:
    Foo m_foo;
  public:
    Bar( /* ... */ ) : m_foo(calculate_something()) {
    }
private:
    static int calculate_something()
    {
       int something = 0;
       // lot of code to calculate something
       return something;
    }
};

Does this complex initialization code actually belong to Bar ? 这个复杂的初始化代码实际上属于 Bar吗? It may be good to consider having a separate class to just do this initializing. 考虑让一个单独的类来进行初始化可能是件好事。 Something like 就像是

class Bar {
  public:
    Bar(int param, Foo foo): m_foo(foo) {
        // do just some very simple calculations, or use only constructor initialization list
    }
  ...
}

class BarBuilder {
  public:
    BarBuilder(/*...*/) {
        // do all calculations, boiling down to a few parameters for Bar and Foo
       Foo foo(fooParameter);
       m_result = new Bar(barParameter, foo); // give Foo here explicitly
    }
    Bar getResult() { return *m_result; }
  private:
    Bar* m_result; // or better use unique_ptr  
}

This also opens the way to a full Builder pattern that might be useful in case, for example, you do not always need all that complex calculations. 这也打开了通向完整的Builder模式的方式,这种模式可能非常有用,例如,您并不总是需要所有复杂的计算。

This assumes all classes to be copy-constructible, but you may more-or-less easily modify it to support what you need. 这假定所有类都是可复制构造的,但您可以或多或少地轻松地修改它以支持您所需的类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何初始化不可默认构造的不可复制对象的元组? - How to initialize a tuple of non-default-constructible not-copyable objects? 如何初始化std :: array <T, 2> 其中T是不可复制的,非默认可构造的? - How to initialize an std::array<T, 2> where T is non-copyable and non-default-constructible? 移动具有非默认构造 class 保护的构造函数 - Move constructor with protection for non-default-constructible class 创建非默认可构造类的虚拟对象 - Create dummy object of non-default-constructible class 如何创建C ++ 11不可默认构造的分配器? - How to create a C++ 11 non-default-constructible allocator? 如何使用 C++ 11 样式的非默认构造分配器指定初始大小? - How to specify an initial size using C++ 11 style non-default-constructible allocator? 初始化非默认可构造元素的 std::array? - Initializing an std::array of non-default-constructible elements? 使用 Boost.Python 导出非默认可构造类 - Exporting non-default-constructible classes with Boost.Python 使用非默认可构造类型填充std :: array(无可变参数模板) - Populate std::array with non-default-constructible type (no variadic templates) 使用不可默认构造的映射值添加到 std::map - add to std::map with a non-default-constructible mapped value
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM