2009-10-12 2 views
0

У меня есть случайный вопрос о корректности 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 я получаю сообщение об ошибке, что он не может преобразовать этот указатель из сопзИ Foo Foo к &. Это имеет смысл с момента вызова функции non 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

Спасибо, что имеет смысл, я выставляю код для singleton. Я не написал этот код, я пытаюсь его понять. – UberJumper

0

Да, это просто небезопасно.

Инструменты не имеют (прямолинейного) способа узнать, что 'const' на Foo :: GetOrSet будет применяться к тому же экземпляру Foo, что и Foo :: GetInstance().

«Singleton» - это не политика, которая означает что-либо для компилятора.

0

Потому что компилятор заботится только о доступе к this. Это не касается проверки всех путей, которые могут изменить ваш объект. Так что да, это работает. Это небезопасно? Это зависит от :) Не должно быть в большинстве случаев, но обязательно есть множество обстоятельств, которые могут заставить все это упасть.

1

Его не то, что его небезопасно, его просто совершенно нелогично. Если вы не хотите иметь константу этого указателя, чем не указывать функцию как const. Это так просто. В любом случае компилятор не может сильно оптимизировать.

Причина, по которой он работает, заключается в том, что singleton передает новый этот указатель, не унаследованный от родительской функции. Не имеет значения, что они представляют собой один и тот же адрес. Один из них const, который функция не может использовать. Один из них не является

1

Код иллюстрирует, что не имеет большого смысла иметь указатель на константу singleton, когда вы можете в любое время захватить неконстантную ссылку на синглтон, через глобальный getter , Глобальный геттер говорит: «Конечно, любой может изменить объект в любое время. Это нормально». Функция-член const говорит: «О, нет, было бы очень плохо изменить этот объект».

Если класс не был одноточечным, так что он не был уверен, что this относится к тому же объекту, который возвращает GetInstance, то это может иметь смысл во многих случаях.Поскольку они относятся к одному и тому же объекту, и все знают, что они делают, потому что это одноэлемент, они не могут быть правы.

Вы никогда не сможете предположить, что какой-либо объект с глобальным доступом не будет изменен (по крайней мере, вы не можете предположить, что система const поможет вам избежать его модификации - могут быть некоторые другие свойства класса, которые делать гарантии об изменениях). Таким образом, либо GetInstance небезопасен, либо мотивы лица, вызывающего функции-члены на const Foo, являются небезопасными, в зависимости от того, кто на самом деле правилен в отношении того, должен ли объект быть изменен в данном бите кода. В этом случае я не уверен, что смысл определения любых функций-членов const объекта, который может быть модифицирован на глобальном уровне - если у кого-то есть ссылка на const, то откуда они берут эту ссылку и почему? И что заставляет кого-то думать, что функция «Get OrSet» должна быть const в первую очередь?

Один из вариантов для GetInstance вернуться const Foo&, но есть некоторые mutable переменных-членов для вещей, которые это нормально для любого изменения, в любое время, даже через константную ссылку. Но это зависит от того, что Foo действительно для: mutable действительно должен использоваться только для таких вещей, как кеши, которые не изменяют «наблюдаемое» гарантированное поведение объекта.

Смежные вопросы