【问题标题】:C++ Singleton Instance disable re-callC++ 单例实例禁用重新调用
【发布时间】:2018-07-30 15:16:57
【问题描述】:

使用 Meyers 单例时:

class Singleton
{
public:
    static Singleton& instance()
    {
        static Singleton instance;
        return instance;
    }

    void Hello()
    {
        std::cout <<"Hello!\n";
    }

protected:
    Singleton() = default;
    ~Singleton() {};

private:
    Singleton(Singleton const&);
    Singleton& operator=( Singleton const& );
};

您可以按如下方式调用实例:

Singleton::instance().Hello();

Singleton& s = Singleton::instance();
s.Hello();

但我想知道是否有办法阻止它:

Singleton::instance().instance();

如何避免将 instance() 作为方法调用(使用.)并且只支持使用:: 的静态调用?

有没有办法使用 static_assert、模板 enable_if 或其他任何东西?

【问题讨论】:

  • 有什么理由要禁止它吗?只是好奇
  • 您可以将生命周期管理外包到SingletonHolder(可能是类模板)。这样,SingletonHolder&lt;MyType&gt;::instance() 返回一个没有instance() 方法的对象。请看“现代 C++ 设计”的第 6 章,其中详细介绍了这种包装器技术。
  • 让 Meyer 的单身死去吧……
  • @Rakete1111 不,没有。我只想禁用它,因为它会误导调用另一个实例。因此,如果可能的话,我更喜欢使用 static_assert 的编译时错误。我不想为一件简单的事情做一个巨大的变通办法,如果不可能的话,我可以忍受它。只是想看看可能性,因为我自己找不到。
  • @Vuwox 这不是一种解决方法,Meyers 的 Singleton 在许多层面上都存在缺陷。 Singleton 的使用是有问题的,Meyers 是一个错误。

标签: c++ c++11 static singleton


【解决方案1】:

首先,我认为这不是一个实际问题。没有人会写Singleton::instance().instance().instance().Hello()。或者更确切地说,如果人们是故意写的,我认为你有更大的问题。这很好,照原样。


如果您真的想防止这种情况发生,那么您只需将instance() 移出类,使其不再是成员函数。没有什么可以断言或约束的,因为您无法判断您的静态成员函数是否在对象上被调用(并且您不能使用具有相同参数列表的非静态成员函数重载静态成员函数)。要么你可以同时写Singleton::instance()Singleton::instance().instance(),或者都不写。

最简单的就是:

class Singleton {
    // ... 
    friend Singleton& make_singleton();
};

Singleton& make_singleton() {
    static Singleton instance;
    return instance;
}

现在它只是make_singleton().Hello(),根本没有其他方法可以写它。这可以通过将其包装在单例类模板工厂中来任意概括:

template <typename T>
struct SingletonFactory
    static T& instance() {
        static T instance;
        return instance;
    }
};

SingletonFactory<Singleton>::instance().Hello(); // ok
SingletonFactory<Singleton>::instance().instance().Hello(); // error

【讨论】:

  • 我和工厂一起去了。这可以处理所有对象(如果需要更多单例)。对于这个例子,我们唯一需要注意的是Singleton 有一个私有的ctor/dtor。所以你需要在class Singleton 中添加friend class SingletonFactory&lt;Singleton&gt; 以确保访问私有元素。这样,我可以确保我的类 Singleton 除了使用 SingletonFactory 之外永远不会被创建。
猜你喜欢
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2013-03-24
  • 2015-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多