依赖初始化列表

Depended initializatoin list

我是 C++ 的新手,遇到了这个设计问题。

假设我有这些 classes:

class Dependee
{
public:
    // Constructors
    initialize();
};

class Depender
{
public:
    Depender(Dependee dependee);
    // Other constructors and stuff
};

class World
{
public:
    World();
private:
    Dependee dependee_;
    Depender depender_;
};

现在depender依赖dependee进行构建。但是dependee不仅要在depender的构造之前构造,还要使用initialize()进行初始化。

有几种方法可以解决这个问题,我正在考虑的两个是World里面的静态方法class

static Dependee initDependee()
{
    Dependee dependee();
    if(!dependee.initialize())
    {
        throw SomeException();
    }

    return dependee;
}

然后做:

World::World():
dependee_(initDependee()),
depender_(dependee_)
{}    

或者只使用默认构造函数初始化两者,然后在 World 的构造函数中完成其余工作

World::World() :
dependee_(),
depender_()
{
    Dependee dependee();
    dependee.initialize();

    dependee_ = dependee;

    Depender depender(dependee);

    depender_ = depender;
}

显然我对任何其他解决方案持开放态度,但考虑到 Dependee 来自外部图书馆。

PS:有没有推荐的关于正确的 C++ 设计和编码约定的好书?

谢谢!

无论哪种方式,您都在生成大量副本。我会用共享指针来做,除非你真的 需要Dependee 的单独副本存储在 WorldDepender.

class Dependee
{
public:
    // Constructors
    initialize();
};

class Depender
{
public:
    Depender(shared_ptr<Dependee> dependee);
    // Other constructors and stuff
};

class World
{
public:
    World() : dependee_(new Dependee())
    {
        dependee_.initialize();
        depender_.reset(new Depender(dependee_));
    }
private:
    shared_ptr<Dependee> dependee_;
    shared_ptr<Depender> depender_;
};

这样您只需构建和存储每个对象的 1 个副本。

两阶段初始化通常是不明智的。 C++有构造函数!但是,考虑到它来自第三方库并且您对此无能为力,我当然不建议为您的 Depender 使用默认构造函数。发明构造函数(当然,还有其他一些东西)是为了保留 class 不变量。

您的静态初始化程序的问题当然是您的 Dependee 的复制构造。现在,您需要在您的依赖者 class 中复制一份您的依赖者的副本吗?或者指针可以吗?显然,如果是指针,你可以简单地使用unique_ptr。有问题吗?当然,动态分配并不总是首选。

那么你会如何解决这个难题呢?我会建议一个包装纸。像这样:

template <class WRAPPEE> struct Wrapper {
    Wrapper() { wrappee.initialize(); }
    WRAPPEE& operator() { return wrappee; } // Add const version as well
private:
    WRAPPEE wrappee;
};

typedef Wrapper<Dependee> dependee_t;
dependee_t dependee;
....
depender(dependee);

这应该工作得很好。