我有一个关于const正确性的随机问题。
假设我有一个单身的课程。
class Foo : public Singleton<Foo>
{
friend class Singleton<Foo>;
public:
std::wstring GetOrSet(const int id) const;
private:
Foo();
~Foo();
void LoadStringIntoMap(const int id, const std::wstring &msg);
std::map<int, std::wstring> strMap;
};
函数定义为
std::wstring Foo::GetOrSet(const int stringId) const
{
if ( strMap.find(stringId) == strMap.end() )
{
Foo::GetInstance()->LoadStringIntoMap(stringId, std::wstring(L"HELLO WORLD222"));
}
std::map<int, std::wstring>::const_iterator retStr = strMap.find(stringId);
return retStr->second;
}
void Foo::LoadStringIntoMap(const int stringId, const std::wstring &msg)
{
strMap.insert(std::pair<int, std::wstring>(stringId, msg));
}
如果我直接调用LoadStringIntoMap我得到一个错误,它无法将此指针从const Foo转换为Foo&amp ;.这是有道理的,因为你在const函数中调用非const函数。但是,在调用单例时,为什么这不是问题,并通过它进行修改。
这真的不安全吗?
这就是单身人士被定义为:
template <typename T> class Singleton
{
protected:
Singleton () {};
~Singleton () {};
public:
static T *GetInstance()
{
return (static_cast<T*> (m_This));
}
static void Destroy()
{
if(m_This != NULL)
delete m_This;
}
static void CreateInstance()
{
m_This = GetInstance();
if (m_This == NULL)
{
m_This = new T;
}
}
private:
// Unique instance
static T *m_This;
};
template <typename T> T *Singleton<T>::m_This = NULL;
答案 0 :(得分:3)
GetInstance()
返回非const
指针。
由于函数GetInstance()
未绑定到对象本身,而是在类范围内绑定,因此可以从const
函数调用它。
基本上,你已经把自己赶出了const
环境;但是,你可以从程序的任何上下文/状态中做到这一点(成员的私有性不受特定对象的约束,只有类)。在这种情况下,您必须自己关心单例访问器的安全使用。
答案 1 :(得分:1)
它的不安全性并非完全不合逻辑。如果你不希望有一个常量这个指针而不是将函数指定为const。就这么简单。无论如何,编译器无法进行太多优化。
它起作用的原因是因为单例传递一个新的this指针而不是从父函数继承的。它们都是相同的地址并不重要。一个是函数不能使用的const。一个不是
答案 2 :(得分:1)
代码说明,当你可以通过全局getter随时获取对单例的非const引用时,有一个指向单例的const指针没有多大意义。全球吸气者说,“当然,任何人都可以随时修改物体。这很好”。 const成员函数说:“哦,不,修改这个对象真的很糟糕。”
如果类不是单例,那么不确定this
是否指向GetInstance
返回的同一对象,那么在很多情况下这可能是完全合理的。既然他们确实引用了同一个对象,并且每个人都知道他们这样做是因为它是单身,他们不可能都是对的。
你不能假设某些全局可访问的对象不会被修改(至少,你不能假设const系统会帮助你避免修改它 - 这个类可能还有一些其他的属性保证有关修改)。因此,GetInstance
或者const Foo
是不安全的,或者const
上调用成员函数的人的动机是不安全的,这取决于在给定的代码位中是否应该修改对象的实际对象。在这种情况下,我不确定定义一个可全局修改的对象的任何GetInstance
成员函数是什么意思 - 如果某人有一个const引用,那么他们从哪里获得该引用,以及为什么?是什么让任何人认为一个名为“Get OrSet ”的函数首先应该是const?
一个选项是const Foo&
返回mutable
,但有一些mutable
成员变量可供任何人随时修改,甚至可以通过const引用。但这取决于Foo实际上的用途:{{1}}实际上只应用于不修改对象的“可观察”保证行为的缓存之类的东西。
答案 3 :(得分:0)
是的,这只是不安全。
这些工具没有任何(直接)方式知道Foo :: GetOrSet上的'const'将应用于与Foo :: GetInstance()相同的Foo实例。
'Singleton'不是一个对编译器有意义的策略。
答案 4 :(得分:0)
因为编译器只关心对this
的访问。它不会检查所有可以更改对象的路径。所以是的,它有效。这不安全吗?这取决于:)在大多数情况下不应该,但确定有一系列情况可以使它全部崩溃。