【问题标题】:How to properly initialize non-default-constructible class member?如何正确初始化非默认可构造类成员?
【发布时间】:2015-10-19 09:44:37
【问题描述】:

假设我定义了一个类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 */
    }
};

显示的代码不会运行,因为Bar 正在尝试调用Foo 的默认构造函数。

现在我要做的是让Bar 的构造函数首先确定something,然后将结果传递给Foo 的构造函数。

解决此问题的一种方法是让Bar 仅拥有指向Foo 的引用/指针,并在确定m_something 后对其进行初始化。但是,我想避免这种情况,以明确 m_foo 的生命周期完全取决于所属类的生命周期。

另一种方法是在Foo 中实现一个默认构造函数并稍后设置该值,我也想避免这种情况,因为Foo 的任何实例都应该具有其成员的有效值(在任何时候) .

实现这一点的正确方法是什么?我在这里被引用/指针卡住了吗?

【问题讨论】:

    标签: c++ class constructor initialization member


    【解决方案1】:

    最好的办法是创建辅助函数,它会计算一些东西,然后在构造函数初始化列表中初始化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;
        }
    };
    

    【讨论】:

    • 感谢您的回答。我也考虑过这样做,但是在这种情况下,我还必须将 Bar 的大部分初始化移动到辅助函数中,因为 something 取决于此。
    • @madmax1 不好。然后独立计算一些东西,或者使用你的一个想法(指针,或默认构造Foo)。
    【解决方案2】:

    这个复杂的初始化代码真的属于Bar吗?考虑有一个 separate 类来进行初始化可能会很好。类似的东西

    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  
    }
    

    这也为实现完整的 Builder 模式开辟了道路,例如,在您并不总是需要所有复杂计算的情况下,该模式可能很有用。

    这假定所有类都是可复制构造的,但您可以或多或少轻松地对其进行修改以支持您的需求。

    【讨论】:

      猜你喜欢
      • 2011-08-09
      • 1970-01-01
      • 2018-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多