2009-10-12 81 views
0

我有一个关于const正确性的随机问题。Const正确性问题C++

可以说我有一个单身人士的班级。

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我得到一个错误,它无法this指针从常量富转换为foo &。这是有道理的,因为你在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; 

回答

3

GetInstance()返回非const指针。 由于函数GetInstance()没有绑定到对象本身,而是整个类,所以可以从const函数调用它。

本质上,你已经欺骗了const环境;但是,你可以从程序的任何上下文/状态中做到这一点(成员的私密性并不局限于特定的对象,只有类)。在这种情况下,您必须自己关心安全使用单例访问器。

+0

由于这是有道理的,我把代码为单身。我没有写这个代码,我试图理解它。 – UberJumper 2009-10-12 16:45:57

0

是的,它只是不安全。

这些工具没有任何(直截了当)的方式知道Foo :: GetOrSet上的'const'将与Foo :: GetInstance()应用于Foo的相同实例。

'Singleton'不是一个对编译器意味着什么的策略。

0

因为编译器只关心访问this。它不会检查所有可以改变对象的路径。所以是的,它的工作原理。它不安全吗?这取决于:)不应该在大多数情况下,但肯定有一系列的情况,可以使其全部倒下。

1

它并不是它的不安全,它完全不合逻辑。如果你不想有一个常量指针,而不是指定函数为const。它很简单。无论如何,编译器无法做很多优化。

它工作的原因是因为单例传递了一个新的指针NOT不是从父函数继承的。无关紧要,它们都是相同的地址..一个是函数不能使用的const。其中一个不是

1

该代码说明,如果有一个指向单例的const指针,那么当您可以随时通过全局getter获取对该单例的非常量引用时,它没有多大意义。全球吸气者说:“当然,任何人都可以随时修改物体,这很好。” const成员函数说:“哦,不,修改这个对象真的很糟糕”。

如果班级不是单身人士,因此不能确定this是指与GetInstance返回的同一个对象,那么在很多情况下这可能会很有意义。既然他们确实提到同一个对象,并且每个人都知道他们是因为它是单身人士,他们不可能都是对的。

你永远不能假定一些全局可访问的对象不会被修改(至少,你不能假设const的系统将帮助你避免修改它 - 有可能是一些类的其他特性,这保证修改)。因此,无论GetInstance是不安全的,或调用在const Foo成员函数的人的动机是不安全的,这取决于谁是是否对象应在代码的给定的位被修改实际上是正确的。在这种情况下,我不知道该点是一个定义对象,它是全球范围内修改的任何const成员函数的东西 - 如果有人有一个常量引用它,那么他们在何处得到该引用,又为什么?是什么让任何人想调用的函数“获取OrSet”应摆在首位常量?

一个选项是GetInstance返回const Foo&,但有一些mutable成员变量,任何人都可以随时修改,甚至通过const引用。但是这取决于富实际上是什么:mutable真的应该只用于诸如不修改对象的“可观察的”保证行为缓存。