如何防止方法的调用者将结果存储在C ++中

时间:2017-07-12 06:53:27

标签: c++

假设我有一个Singleton类。如何防止调用者将调用结果存储到getInstance()方法?

我需要这个,因为在执行期间可以修改单例的实例,并且其他类中的任何存储实例都将失效。我的解决方案是强制所有调用者每次想要使用Singleton实例时调用getInstance()。

class Singleton
{
    private:
        static Singleton* instance;

    private:
        Singleton();

    public:
        static Singleton* getInstance();
};

Singleton* Singleton::instance = nullptr;

Singleton* Singleton::getInstance()
{
    if (instance == nullptr)
    {
        instance = new Singleton();
    }

    return instance;
}

class A
{
private:
    Singleton* m_singleton;

public:
    A()
        : m_singleton(Singleton::getInstance()) //This should not be possible
    {
    }
};

int main()
{
    A a;

    return 0;
}

我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:2)

你做不到。如果您的getInstance()返回指针或引用,则无法阻止将结果复制到某个变量中,就像您无法阻止类型为intdouble的结果一样从被复制。

然而,您可以使单例提供静态的函数:

class SomeSingleton
{
public:
    static void foo();
private:
    // deleting copy constructor and assignment operator...
    static SomeSingleton* getInstance();
};

void SomeSingleton::foo()
{
    SomeSingleton* instance = getInstance();
    // use instance as you need to get the appropriate result
}

所以你强制执行这样的用法:

SomeSingleton::foo();

有些人甚至认为使用起来比

更舒服
SomeSingleton::getInstance().foo();

顺便说一句:如果多线程出现问题或者出现问题,这种方法可以保护您免受竞争条件的影响:

class SomeSingleton
{
public:
    static void foo();
private:
    static std::mutex mutex; // <- add a mutex!

    static SomeSingleton* getInstance();

    static void exchange();
};

void SomeSingleton::foo()
{
    // this must be added whenever the singleton is used...
    std::lock_guard<std::mutex> guard(mutex);

    SomeSingleton* instance = getInstance();
    // use instance as you need to get the appropriate result
}

void SomeSingleton::exchange()
{
    // ... or the singleton instance is re-asigned
    std::lock_guard<std::mutex> guard(mutex);

    SomeSingleton* newInstance = new SomeSingleton();
    delete instance;
    instance = newInstance;
}

答案 1 :(得分:1)

我的解决方案是一个包含重载->运算符的包装器,就像在智能指针中调用getInstance()一样:

class Singleton {
    friend SingletonWrapper;
    private:
        static Singleton * getInstance() {...}
    public:
        void foo() {}
};

class SingletonWrapper {
    public:
    Singleton * operator->() {
        return Singleton::getInstance();
    }
};

int main() {
    SingletonWrapper w;
    w->foo();
}

答案 2 :(得分:0)

首先,我不建议使用指针作为单身人士。这("Meyer Singleton")是一种更好的方法。

static SingletonDatabase &get() {
   static SingletonDatabase db;
   return db;
}

同样存储单身是一个坏主意,就像存储你验证单身背后的初始想法/目的一样:你正在制作副本,因此单身不是&#34;唯一的&#34;班级的实例。

无论如何,你的问题的一个很好的解决方案是使用某种信号/插槽系统。 (Qt / Boost库)一旦发生变化,你就可以发出信号,然后被发现#34;通过所有实例并实现值。

Boost Signals / Slots Qt Signals Slots

我希望这会有所帮助:)

答案 3 :(得分:0)

使用volatile来声明单例变量。这将强制编译器始终检查它

class Singleton
{
    private:
        static volatile Singleton* instance;

    private:
        Singleton();

    public:
        static volatile Singleton* getInstance();
};