C ++中的Const正确性问题

时间:2009-10-12 16:28:07

标签: c++ const

我有一个关于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;

5 个答案:

答案 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的访问。它不会检查所有可以更改对象的路径。所以是的,它有效。这不安全吗?这取决于:)在大多数情况下不应该,但确定有一系列情况可以使它全部崩溃。