类成员初始化的最佳实践

时间:2015-11-12 22:57:36

标签: c++ class 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'还有一个set方法

Foo::Foo
{
    mBar = new Bar();
}

Foo::Initialize()
{
    mBar->SetMembers("some", "required", "members");
}

1 个答案:

答案 0 :(得分:5)

Foo构造函数中执行所有操作!

在构造函数中完成所有构造和初始化!这称为RAII: resource acquisition is initialisation。分配资源,在这种情况下,Foo也应该初始化资源。这也使您的界面易于使用:Foo 无法,而无需先构建Foo。一旦构造,假设它初始化其构造函数中的所有内容,它就可以使用了。如果您希望呼叫者也必须调用InitializeSet函数,那么您的类界面很难使用。如果Foo尚未首次调用,Initialize将如何响应函数调用?突然,每个功能都需要具备以下功能:

bool Foo::SomeFunction()
{
    if (!mBar->isInitialized())
        return false;

    // Do what we came here to do
    return true;
}

现在,来电者必须经常检查您的功能的返回值。如果函数需要返回一个值,但由于mBar未初始化而必须指示错误,该怎么办?

一旦离开RAII,你就可以看到兔子洞很深:资源分配初始化!

来自Effective C++ Third Edition - Scott Myers

  

第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;
};