假设我有一个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;
}
我怎样才能做到这一点?
答案 0 :(得分:2)
你做不到。如果您的getInstance()
返回指针或引用,则无法阻止将结果复制到某个变量中,就像您无法阻止类型为int
或double
的结果一样从被复制。
然而,您可以使单例提供静态的函数:
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();
};