使用singleton防止类/实例访问中的重复对象

时间:2016-09-22 15:34:37

标签: c++ singleton

用法是提供.instance访问,也是为了防止这些类的重复对象。

这是单例的良好代码实现吗?

template <typename T> class singleton
{
public:
    static T *ms_singleton;

    singleton()
    {
        assert(!ms_singleton);
        long offset = (long)(T *) 1 - (long)(singleton <T> *)(T *) 1;
        ms_singleton = (T *)((long) this + offset);
    }

    virtual ~singleton()
    {
        assert(ms_singleton);
        ms_singleton = 0;
    }

    static T &instance()
    {
        assert(ms_singleton);
        return (*ms_singleton);
    }

    static T &Instance()
    {
        assert(ms_singleton);
        return (*ms_singleton);
    }

    static T *instance_ptr()
    {
        return (ms_singleton);
    }
};
template <typename T> T *singleton <T>::ms_singleton = NULL;

我如何使用它:

class test1: public singleton<test2>
{
    // Something
};

如果没有,这里有什么问题?我应该在这里重写一下?

1 个答案:

答案 0 :(得分:1)

你的单身人士课有一些奇怪的事情。就像你依靠构造函数在构造函数中进行调试构建运行时检查它是否可以构造一样。

典型的单例类具有私有的构造函数,因此它只能由访问器函数构造。它也不应该依赖于例如assert这是在发布版本中禁用的宏。

一个简单的不可继承的单例类可能如下所示:

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

    // Other public member functions

private:
    // Private constructor
    Singleton() = default;
};

通过将构造函数设为私有,这意味着没有其他人不能尝试构造实例。这也意味着在编译器编译时会检查它。

此外,通过将对象的实际实例作为静态变量在访问器函数内的定义中初始化,意味着实例的创建是线程安全的。

要扩展它并使其像您似乎想做的那样通用,那么您需要使基类构造函数受到保护。您还需要在继承的类中将基类设为friend

子类仍需要将其构造函数设为私有,以防止意外构建。

更新后的基类看起来像

template<typename T>
class Singleton
{
public:
    static T& instance()
    {
        static T actual_instance;
        return actual_instance;
    }

protected:
    Singleton() = default;
};

子类看起来像

class ChildSingleton : public Singleton<ChildSingleton>
{
public:
    // Public member functions...

private:
    friend class Singleton<ChildSingleton>;

    // Private constructor
    ChildSingleton() = default;
};