类成员初始化的最佳实践
Best practice for class member initialization
假设我有一个类Foo:
class Foo
{
public:
Foo();
~Foo();
private:
Bar* mBar;
}
并且假设"Bar"是一个包含一些需要初始化的成员的类。初始化该成员时使用的最佳做法是什么?
示例1:在Foos构造函数中执行所有操作
Foo::Foo()
{
mBar = new Bar("some", "required", "members");
}
示例2:创建一个单独的初始化函数:
Foo::Foo()
{
}
Foo::Initialize()
{
mBar = new Bar("some", "required", "members");
}
示例3:两部分初始化,假设"Bar"也有一个设置方法
Foo::Foo
{
mBar = new Bar();
}
Foo::Initialize()
{
mBar->SetMembers("some", "required", "members");
}
在Foo
构造函数中执行所有操作
在构造函数中进行所有构造和初始化!这被称为RAII:资源获取是初始化。在分配资源时,在这种情况下,Foo
也应该初始化资源。这也使您的界面易于使用:如果不首先构造Foo
,就不能使用Foo
。一旦构造好,假设它初始化了构造函数中的所有内容,就可以使用了。如果您希望调用者也必须调用Initialize
或Set
函数,那么您的类接口就很难使用。如果Initialize
尚未被首次调用,Foo
将如何响应函数调用?突然间,每个功能都需要具备以下功能:
bool Foo::SomeFunction()
{
if (!mBar->isInitialized())
return false;
// Do what we came here to do
return true;
}
现在,调用者必须不断地检查函数的返回值。如果函数需要返回一个值,但由于mBar
没有初始化而不得不指示错误,该怎么办?
你可以看到,一旦离开RAII,兔子洞就会很深:资源分配就是初始化!
从有效的C++第三版-斯科特迈尔斯:
第4项:确保对象在使用前已初始化
…
初始化的责任落在构造函数身上。规则很简单:确保所有构造函数都初始化对象中的所有内容
其他建议
您还应该更喜欢使用构造函数初始值设定项列表来构建成员:
Foo::Foo() : mBar(new mBar("some", "required", "members"))
{
}
否则,您将进行不必要的复制。我还认为您使用指针是有充分理由的。正如@Niels van Eldik在评论中指出的那样,除非你真的需要使用指针,否则你应该使用对象,在这种情况下,你应该使用最适合你需求的智能指针(在这种情况中,我几乎可以猜测,说std::unique_ptr
:
class Foo
{
public:
Foo() : mBar(std::make_unique<Bar>("some", "required", "members"))
{
}
private:
std::unique_ptr<Bar> mBar;
};
相关文章:
- 在派生类中使用基类的私有成员变量的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- 可以具有不同基成员实现的类的最佳实现
- 删除类成员的动态分配内存的最佳方法是什么
- 在指向现有内存地址的 hpp 文件中声明成员函数的最佳方法
- std::使用类成员函数创建线程 - 最佳实践
- 使用相同方法但不同成员类型构建类的最佳方法
- 在函数中使用 const 引用参数访问函数中成员的最佳实践 C++.
- 返回可能在C++中分配在堆栈上的成员时,最佳指针/引用类型是什么
- 成员变量的初始化必须延迟。此类的最佳设计选择是什么?
- 在抽象基类中与抽象类成员合作的最佳方法
- 具有许多成员变量的课程的最佳实践
- 访问成员变量或访问成员函数是最佳选择
- 在C++中将迭代器存储为类成员的最佳实践
- 获取私有实例变量容器成员值的最佳方式
- C++是修改这些对象的向量中所有对象的给定成员的最佳方法
- 复制包含STL成员(如vector)的C++结构的最佳方法是什么
- 最佳实践:访问向量中具有不同成员变量和方法的派生类
- 私有类成员延迟初始化的最佳做法
- 组织专用成员 Vector<Vector 接口的最佳方式<Type>>