依赖初始化列表

Depended initializatoin list

本文关键字:列表 初始化 依赖      更新时间:2023-10-16

我对c++有点陌生,遇到了这个设计问题。

假设我有这些类:

class Dependee
{
public:
    // Constructors
    initialize();
};
class Depender
{
public:
    Depender(Dependee dependee);
    // Other constructors and stuff
};
class World
{
public:
    World();
private:
    Dependee dependee_;
    Depender depender_;
};

现在,依赖于依赖的构造。但是depended不仅要在dependder的构造之前被构造,而且要使用initialize()进行初始化。

有几种方法可以解决这个问题,我正在考虑的两种方法是在World类 中使用静态方法。
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++设计和编码规范的好书吗?

谢谢!

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

静态初始化器的问题当然是依赖对象的复制构造。现在,在依赖类中需要依赖对象的副本吗?或者一个指针也行?显然,如果它是指针,您可以简单地使用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);

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

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

这样你只构造和存储每个对象的一个副本。