初始化类成员的更好的做法是什么?

Chm*_*lok 2 c++ c++17

我们假设我有一个看起来像这样的A类:

class A {
public:
  public A(bool someFlag, Params someParams);
private:
  vector<string> texts;
}
Run Code Online (Sandbox Code Playgroud)

我想提取初始化texts成员字段的逻辑.我想出了两个想法:

  1. 第一个想法 - 静态的私有成员函数,它将返回所需的文本向量.

    A::A(bool someFlag, Params someParams) {
      if (someFlag)
        texts = createSomeTexts(someParams);
      else
        texts = createOtherTexts(someParams);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 第二个想法-这将分配给文本类成员的期望矢量私有成员函数本身.

    A::A(bool someFlag, Params someParams) {
      if (someFlag)
        createAndAssignSomeTexts(someParams);
      else
        createAndAssignOtherTexts(someParams);
    }
    
    Run Code Online (Sandbox Code Playgroud)

当然,两个版本都能正确完成工作,但我想知道对于这些情况的建议方法是什么.此外,如果成员初始化需要更多参数(尤其是作为成员存储在类中的参数),则该方法应该更改.

lub*_*bgr 8

您应该努力初始化数据成员,而不是在构造函数体中分配它们.您显示的两个版本都会导致std::vector<std::string>实例的默认构造,并在以后分配给它.因此,我建议:

A::A(bool someFlag, const Params& someParams) :
    texts(someFlag ? createSomeTexts(someParams) : createOtherTexts(someParams))
{}
Run Code Online (Sandbox Code Playgroud)

或者,更可读,让我们createSomeTexts处理旗帜:

A::A(bool someFlag, const Params& someParams) :
    texts(createSomeTexts(someFlag, someParams))
{}
Run Code Online (Sandbox Code Playgroud)

createSomeTexts如果需要访问其他数据成员,请创建成员函数(确保它们在texts成员之前声明并正确初始化 - 正如@Scheff指出的那样,这不太可能是一个好主意).否则,使它成为一个自由函数(请参阅此处为什么这是可取的).曾经createSomeTexts是一个自由函数,你可以像这样构造对象:

std::vector<std::string> stringsToInject = createSomeText(/* Some flags.... */);

A instance(stringsToInject); // A's ctor updated to make this work 
Run Code Online (Sandbox Code Playgroud)

这可以进一步分离关注点作为A负责初始化数据成员的构造函数,而创建初始化数据的逻辑位于其他地方.

  • 一个成员函数,在构造函数中调用但访问其他成员......这听起来不是一个好主意.(而不是像你自己的脚或更晚的射击设计.);-) (8认同)
  • 是的,这在技术上是可行的,因为成员的施工顺序是明确的.但考虑到代码是由人类编写而忽略了事情并且有时会丢失代码数量,这是非常脆弱的... ;-) (3认同)