C++ C++;

C++ C++;,c++,constants,C++,Constants,我有一个关于常数正确性的随机问题 假设我有一个单身的班级 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:

我有一个关于常数正确性的随机问题

假设我有一个单身的班级

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;
};
class-Foo:公共单例
{
朋友班单身;
公众:
std::wstring GetOrSet(const int id)const;
私人:
Foo();
~Foo();
void LoadStringIntoMap(const int id,const std::wstring&msg);
标准:映射标准映射;
};
这些函数的定义是这样的

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));
}
std::wstring Foo::GetOrSet(const int stringId)const
{
if(strMap.find(stringId)=strMap.end())
{
Foo::GetInstance()->LoadStringToMap(stringId,std::wstring(L“HELLO WORLD222”);
}
std::map::const_迭代器retStr=strMap.find(stringId);
返回retStr->second;
}
void Foo::LoadStringIntoMap(常量int stringId、常量std::wstring&msg)
{    
strMap.insert(std::pair(stringId,msg));
}
如果我直接得到call LoadStringIntoMap,我会得到一个错误,它无法将这个指针从const Foo转换为Foo&。这是有意义的,因为您从常量函数中调用非常量函数。但是为什么在调用singleton并通过它进行修改时这不是一个问题呢

这真的不安全吗

这就是singleton的定义:

   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;
模板类单例
{
受保护的:
单态(){};
~Singleton(){};
公众:
静态T*GetInstance()
{
返回(静态_cast(m_This));
}
静态空洞破坏()
{
如果(m_This!=NULL)
删除此项;
}
静态void CreateInstance()
{
m_This=GetInstance();
如果(m_This==NULL)
{
m_This=新T;
}
}
私人:
//唯一实例
静态T*mu这;
};
模板T*单例::m_This=NULL;
是的,它只是不安全

这些工具没有任何(直接的)方式知道Foo::GetOrSet上的“const”将应用于Foo::GetInstance()的同一个Foo实例

“Singleton”不是一个对编译器有任何意义的策略。

是的,它只是不安全

这些工具没有任何(直接的)方式知道Foo::GetOrSet上的“const”将应用于Foo::GetInstance()的同一个Foo实例

“Singleton”不是对编译器有任何意义的策略。

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

本质上,你已经把自己从
const
环境中骗了出来;但是,您可以从程序的任何上下文/状态执行此操作(成员的私有性不受特定对象的约束,只受类的约束)。在这种情况下,您必须自己注意单例访问器的安全使用。

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


本质上,你已经把自己从
const
环境中骗了出来;但是,您可以从程序的任何上下文/状态执行此操作(成员的私有性不受特定对象的约束,只受类的约束)。在这种情况下,您必须自己注意单例访问器的安全使用。

因为编译器只关心对
的访问。它甚至没有检查所有可以更改对象的路径。所以是的,它起作用了。它不安全吗?这要视情况而定:)在大多数情况下不应该是这样,但肯定有一系列的情况会让一切都完蛋

因为编译器只关心对
这个
的访问。它甚至没有检查所有可以更改对象的路径。所以是的,它起作用了。它不安全吗?这要视情况而定:)在大多数情况下不应该是这样,但肯定有一系列的情况会让一切都完蛋

这并不是不安全,只是完全不合逻辑。如果您不想在指针上有一个常量,那么不要将函数指定为const。就这么简单。无论如何,编译器无法在那里进行太多优化


它工作的原因是因为单例传递了一个新的this指针,该指针不是从父函数继承的。他们都是同一个地址没关系。。一个是const,函数不能使用它。一个不是

它不是不安全的,只是完全不合逻辑。如果您不想在指针上有一个常量,那么不要将函数指定为const。就这么简单。无论如何,编译器无法在那里进行太多优化


它工作的原因是因为单例传递了一个新的this指针,该指针不是从父函数继承的。他们都是同一个地址没关系。。一个是const,函数不能使用它。一个不是

该代码说明,当您可以通过全局getter随时获取对单例的非常量引用时,使用指向单例的常量指针没有多大意义。全局getter说,“当然,任何人都可以随时修改对象,这很好”。const member函数说,“哦,不,修改这个对象真的很糟糕”

如果类不是单例的,因此不能确定
this
是否引用了
GetInstance
返回的同一个对象,那么在很多情况下,这可能是非常有意义的。因为它们确实引用了同一个对象,而且每个人都知道它们引用了,因为它是单态的,所以它们不可能都是对的

您永远不能假设某些全局可访问对象不会被修改(至少,您不能假设const系统会帮助您避免修改它-类的某些其他属性可能会保证修改)。因此,要么是
GetInstance
不安全,要么是调用
constfoo
a上的成员函数的人的动机