在实例的构造函数中初始化静态成员

时间:2016-07-28 16:54:57

标签: c++ static-members static-initialization

我想在特定实例的构造函数中初始化一个静态成员变量。这是个坏主意吗?

情况如下。我有一个静态成员变量,该类的所有实例都应该共享。通常,我只使用静态初始化程序。但是,在构造函数被调用之前,我没有构造静态对象所需的必要信息。但是当然,我不想每次调用构造函数时都创建一个新对象,所以我想做这样的事情。

class Foo
{
    static Bar * bar;
    Foo( Xyz xyz);
};

Bar * Foo::bar = nullptr;

Foo::Foo(Xyz xyz)
{
    if (Foo::bar == nullptr)
    {
         // initialize static bar 
         Foo::bar = new Bar(xyz);
    }
}

我当然知道xyz对于Foo的构造函数的不同调用,migth会有所不同。这对我来说无关紧要。

这是不好的软件设计?我觉得在构造函数中初始化一个静态对象有点奇怪。但它与单身设计模式没有什么不同。也许这样可以吗?

修改

感谢评论家伙。似乎人们不是这种设计的粉丝。我将对其进行修改,以便在Bar的第一个实例化之前创建一次Foo,并在Bar *的构造函数中传递Foo作为参数。每个Foo都会指向Bar,我会确保所有Foo都指向同一个Bar。那更好吗?

1 个答案:

答案 0 :(得分:1)

  

这是不好的软件设计吗?

一般来说,它会被认为是,是的。 Singleton Pattern 或以这种方式使用静态变量被认为是错误设计的原因有很多。

  

但它与单身设计模式没有什么不同。也许这样可以吗?

如果你真的想要制作 Singleton Pattern ,你应该使用Scott Meyer's technique

class Foo
{
    static Bar* bar(Xyz xyz) {
        static Bar barInstance(xyz);
        return &barInstance;
    }
    Foo( Xyz xyz) : xyz_(xyz) {}

    void baz() {
        Bar* b = bar(xyz_);
        // use b ...
    }

private:
    Xyz xyz_;
};

此代码将是线程安全的,并且无需检查nullptr

虽然Bar应该构成一个 Singleton ,但是你需要在Foo中使用它:

class Bar {
public:
    static Bar& getInstance(Xyz xyz) {
        static Bar barInstance(xyz);
        return &barInstance;
    }

private:
    Bar(Xyz xyz) : xyz_(Xyz) {}
    Bar(const Bar&) delete;
    Bar(Bar&&) delete;
    Bar& operator=(const Bar&) delete;
    Bar& operator=(Bar&) delete;

    Xyz xyz_;
};

class Foo {
public:
    Foo(Xyz xyz) barRef(Bar::getInstance(xyz)) {
                                      // ^^^ Notice 1st instance of Foo created
                                      //     wins to create the Bar actually
    }
private:
    Bar& barRef;
};
相关问题