如何正确初始化非默认构造的 class 成员?
How to properly initialize non-default-constructible class member?
假设我定义了一个 class Foo
,它没有实现默认构造函数。
另外,我有一个classBar
,其中"owns"一个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
只拥有一个 reference/pointer 到 Foo
并在 m_something
确定后初始化它。但是,我想避免这种情况,以明确 m_foo
的生命周期完全取决于拥有者 class.
的生命周期
另一种方法是在 Foo
中实现默认构造函数并稍后设置值,我也想避免这种情况,因为 Foo
的任何实例都应该具有有效值会员(随时)。
实现这个的正确方法是什么?我在这里卡住了 reference/pointer 吗?
最好的办法是创建辅助函数,它会计算一些东西,然后在构造函数初始化列表中初始化 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
吗?最好考虑使用 separate class 来进行初始化。像
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
}
这也为完整的构建器模式开辟了道路,该模式在某些情况下可能很有用,例如,您并不总是需要那么复杂的计算。
这假定所有 class 都是可复制构造的,但您可以或多或少地轻松修改它以支持您的需要。
假设我定义了一个 class Foo
,它没有实现默认构造函数。
另外,我有一个classBar
,其中"owns"一个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
只拥有一个 reference/pointer 到 Foo
并在 m_something
确定后初始化它。但是,我想避免这种情况,以明确 m_foo
的生命周期完全取决于拥有者 class.
另一种方法是在 Foo
中实现默认构造函数并稍后设置值,我也想避免这种情况,因为 Foo
的任何实例都应该具有有效值会员(随时)。
实现这个的正确方法是什么?我在这里卡住了 reference/pointer 吗?
最好的办法是创建辅助函数,它会计算一些东西,然后在构造函数初始化列表中初始化 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
吗?最好考虑使用 separate class 来进行初始化。像
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
}
这也为完整的构建器模式开辟了道路,该模式在某些情况下可能很有用,例如,您并不总是需要那么复杂的计算。
这假定所有 class 都是可复制构造的,但您可以或多或少地轻松修改它以支持您的需要。