假设我有一个看起来像这样的A类:
class A {
public:
public A(bool someFlag, Params someParams);
private:
vector<string> texts;
}
我想提取初始化texts
成员字段的逻辑。
我提出了两个想法:
第一个想法-静态的私有成员函数,可以返回所需的文本向量。
A::A(bool someFlag, Params someParams) {
if (someFlag)
texts = createSomeTexts(someParams);
else
texts = createOtherTexts(someParams);
}
第二个想法-私有成员函数,可以自行将分配给类成员所需的文本向量。
A::A(bool someFlag, Params someParams) {
if (someFlag)
createAndAssignSomeTexts(someParams);
else
createAndAssignOtherTexts(someParams);
}
当然,两个版本都能正确完成工作,但是我想知道针对这些情况的建议方法是什么。另外,如果成员初始化需要更多参数(尤其是作为成员存储在类中的参数),方法是否应该更改。
答案 0 :(得分:8)
您应该努力初始化您的数据成员,而不是在构造函数主体中分配给它们。您显示的两个版本都会导致std::vector<std::string>
实例的默认构造,并在以后分配给它。因此,我建议这样做:
A::A(bool someFlag, const Params& someParams) :
texts(someFlag ? createSomeTexts(someParams) : createOtherTexts(someParams))
{}
或更容易理解的是,让createSomeTexts
也处理该标志:
A::A(bool someFlag, const Params& someParams) :
texts(createSomeTexts(someFlag, someParams))
{}
如果createSomeTexts
需要访问其他数据成员,则使其成为成员函数(确保在texts
成员之前声明它们并正确初始化-正如@Scheff所指出的那样,这不太可能一个好主意)。否则,使其成为自由函数(请参阅here,为什么这是可取的)。一旦createSomeTexts
是一个自由函数,您同样可以像这样构造对象:
std::vector<std::string> stringsToInject = createSomeText(/* Some flags.... */);
A instance(stringsToInject); // A's ctor updated to make this work
由于A
的构造函数负责初始化数据成员,而创建初始化数据的逻辑位于其他地方,因此这可能会进一步分散关注点。
答案 1 :(得分:2)
我将使用情况1,因为函数createSomeTexts和createOtherTexts不会更改任何类变量。这意味着这些功能可以进行单元测试。
最好不要使用全局变量,如果必须的话,不要从全局范围(this->)更改它们,而应通过引用或将其作为指向函数的指针来传递。 这样,您可以在代码中传递存根并编写测试用例。
此外,Params应该是const引用:
class A {
public:
public A(const bool someFlag, const Params &someParams);
private:
vector<string> texts;
}