2009-10-12 7 views
0

const 정확성에 대한 질문이 무작정 있습니다.C++의 Const Correctness Question

내가 싱글 톤인 클래스가 있다고 가정 해 보겠습니다. 내가 직접 내가 그것을 &을 Foo 등을 const를 푸에서이 포인터를 변환 할 수없는 오류가 발생 LoadStringIntoMap 전화를받을 경우

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)); 
} 

로 정의됩니다. 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

0

예, 그냥 안전하지 않은 :

는이 같은 싱글이 정의하는 것이다.

이 도구는 Foo :: GetOrSet에 대한 'const'가 Foo :: GetInstance()와 동일한 Foo 인스턴스에 적용된다는 것을 알 수있는 방법이 없습니다.

'싱글 톤'은 컴파일러에 대한 모든 것을 의미하는 정책이 아닙니다.

0

컴파일러는 this에 대한 액세스에만 신경을 씁니다. 그것은 당신의 물건을 바꿀 수있는 모든 길을 검사하는 것만 큼 멀리 가지 않습니다. 그래서 네, 작동합니다. 안전하지 않나요? 그것은 달려 있습니다 :) 대부분의 경우에 있어서는 안됩니다.하지만 모든 것을 뒤엎을 수있는 일련의 상황이 있는지 확인하십시오.

1

그것의 안전하지 않은 그것의 다만 완전히 비논리적 인. const로 함수를 지정하지 않는 것보다이 포인터를 상수가 아닌 경우. 간단합니다. 컴파일러는 어쨌든 많은 최적화를 수행 할 수 없습니다.

그 이유는 싱글 톤이 부모 함수에서 상속받지 않은 새로운 포인터를 전달하기 때문입니다. 그것은 둘 다 동일한 주소입니다. 하나는 함수가 사용할 수없는 const입니다. 하나가 아니다

1

이 코드는 글로벌 게터를 통해 언제든지 싱글 톤에 대한 비 const 레퍼런스를 잡을 수있을 때 싱글 톤에 대한 const 포인터를 갖는 것이 적절하지 않음을 보여줍니다 . 글로벌 getter는 "물론, 누구든지 원하는 때에 언제든지 객체를 수정할 수 있습니다."라고 말합니다. const 멤버 함수는 "오, 아뇨,이 오브젝트를 수정하는 것은 정말 좋지 않을 것입니다"라고 말합니다.

클래스가 싱글 톤이 아니 어서 thisGetInstance이 반환하는 동일한 개체를 참조하는 것이 확실하지 않은 경우 많은 경우에 완벽합니다.그들은 동일한 객체를 참조하기 때문에 싱글 톤이기 때문에 모두가 알 수 있습니다. 둘 다 옳을 수는 없습니다.

일부 전역 접근 가능 객체가 수정되지 않는다고 추측 할 수 없습니다 (적어도 const 시스템이 수정을 피할 수 있다고 가정 할 수는 없습니다. 클래스의 다른 속성이있을 수 있습니다. 수정에 대한 보증). 따라서 GetInstance이 안전하지 않거나 const Foo에있는 멤버 함수 호출자의 동기는 주어진 코드 비트에서 객체를 수정해야하는지에 대해 실제로 올바른지에 따라 안전하지 않습니다. 이 경우 전역으로 수정할 수있는 객체의 구성원 함수 인 const을 정의하는 것이 무엇인지 모르겠습니다. 누군가가 const 참조를 가지고 있고 그 참조를 어디서 얻었습니까? 왜 그런가요? 그리고 누군가가 "Get OrSet"이라는 함수를 처음부터 const로 생각해야하는 이유는 무엇입니까?

GetInstanceconst Foo&을 반환하지만 언제든지 const 참조를 통해서도 누구나 수정할 수있는 항목에 대해서는 mutable 개의 멤버 변수가 있습니다. 그러나 Foo가 실제로 무엇인지에 달려 있습니다 : mutable은 실제로 객체의 "관찰 가능한"보장 된 동작을 수정하지 않는 캐시와 같은 것에 대해서만 사용해야합니다.