【问题标题】:Initialize static member inside constructor of an instance在实例的构造函数中初始化静态成员
【发布时间】:2016-07-28 16:54:56
【问题描述】:

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

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

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 的构造函数的不同调用可能会有所不同。这对我来说无所谓。

这是糟糕的软件设计吗?我觉得在构造函数中初始化一个静态对象有点奇怪。但这与单例设计模式并没有什么不同。所以也许没关系?

编辑

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

【问题讨论】:

  • 请注意,您不会进行初始化。你会做作业。
  • 如何获得应该用于初始化的值?它仅在运行时可用吗?顺便说一句,您的示例无法编译。
  • 单线程看起来不错。多线程竞争条件。
  • 为什么不使用静态方法并在适当的时候调用它呢?是否需要等到第一次实例化?
  • “但它与单例设计模式并没有太大区别。所以也许没问题?” 大多数有经验的开发人员认为单例模式是不行,甚至是反模式。

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


【解决方案1】:

这是糟糕的软件设计吗?

一般会这样认为,是的。 单例模式或以这种方式使用静态变量被认为是糟糕的设计有很多原因。


但这与单例设计模式并没有什么不同。所以也许没问题?

如果你真的想把它做成一个单例模式,你应该使用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;
};

【讨论】:

  • “但是,在调用构造函数之前,我没有构造静态对象所需的必要信息”...
  • @Jarod42 这表明设计存在缺陷,Bar 不应与Foo 保持静态关系。我只是试图澄清与 real 单例模式的区别。
猜你喜欢
  • 1970-01-01
  • 2014-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
相关资源
最近更新 更多