2016-10-03 5 views
2

가 일정한 기능 someFunc()에서 다음과 같은 상황을모범 사례는

class A 
{ 
public: 
    void someFunc() const 
    { 
     b->nonConstFunction(); //this is a non const function in the class B 
    } 

private: 
    B* b; 
}; 

를 생각 해보자 const를-방법에서 구성원 포인터의 const가 아닌 방법을 액세스 할 때 나는 b의 상수가 메소드를 호출 할 수 있으며 컴파일합니다. 그래서 함수 someFunc()은 어떻게 든 진정한 const 함수가 아닙니다. 하지만 모범 사례에 따르면 const은 어디에서나 할 수 있습니다. 이 조언을 여기서도 적용해야합니까? 함수를 선언 할 수 있습니다 void someFunc() nonconstant 더 정직한 다음 void someFunc() const입니다. 또는 이런 종류의 것들을 다루기위한보다 일반적인 조언이있을 수 있습니까?

+1

정말 '클래스 A'가 무엇을 나타내는가에 따라 달라집니다. 여기에 맞는 크기는 없습니다. – juanchopanza

+0

['mutable'] (http://en.cppreference.com/w/cpp/language/cv) => 다음과 같은 경우는 완벽합니다 : const 환경에서 수정할 수있는 변수를 정의하십시오 클래스 인스턴스에 관계없이 상관하지 않기 때문에 (IMHO, mutex => mutex는 const env에서 수정해야 함) – Garf365

+4

사본에 대한 액세스 권한이 있으면 Effective C++의 항목을 읽는 것이 좋습니다. 논리 대 bitwise constness; 그것은 당신이 지금 당장 가지고있는 혼란입니다. [이 질문] (http://stackoverflow.com/questions/3830367/difference-between-logical-and-physical-const-ness#3830484) 그것에 약간의 토론이 있습니다. – TartanLlama

답변

4

어떻게 든

아니라 진정한 CONST 기능되지 않습니다 :

이 같은 포인터 포함 된 포인터에 const와 전달 래퍼, 뭔가를 만들어이 문제를 해결할 수 , 당신이 표현하고 싶은 것에 달려 있습니다.

  1. A의 국가의 상태가 논리적으로 b에 따라 '경우

    대신,

    • 간단한 해결 방법은 A에게 유형 B의 멤버를 제공하는 것입니다 (이것은 내가 질문에서 얻을 의미입니다) 포인터 나 참조를 사용하는 것. 그런 다음 당신은 당신의 CONST 방법에 const B이 있고,이 귀하의 요구 사항을 표현 직접

    • 다음 간단한은 처음에 const B *b;으로 멤버를 선언하는 것입니다 - 분명히 이것은 당신이 또한 const가 아닌 방법을 필요로하는 경우 작동하지 않습니다 A을 사용하여 b에서 비 const 메소드를 호출하십시오.당신은 간접 필요한 경우

    • 또 다른 가능성은 보장 당신을 줄 것이다

      B* operator->(); 
      const B* operator->() const; 
      

      같은 연산자 오버로드와 스마트 포인터 클래스를 (내가 적당한 사람이 이미 존재하는 경우 확실하지 않습니다)를 사용하는 것입니다 A의의 상태가 하지 논리적 b에 의존 않습니다 '의

  2. 경우합니다.

    이 경우에는 문제가 없습니다. A의 논리 상태가 변경되지 않기 때문에 const 방법에서 b을 돌연변이시키는 것이 좋습니다. 이것은 종종 예를 들어 포인터를 가지고있는 경우 일 수 있습니다. 그렇지 않으면 많은 가변 멤버를 필요로하는 로거.

1

A가 "소유"하지 않는 경우 const입니다. 현대 C++은 b를 unique_ptr로 지정하면 A가 소유자이고 단순한 링크 인 경우 일반 포인터임을 나타냅니다.

1

C++ 전망 B이 같은 A의 일부가되지 않는 것으로 보인다하지만 AB를 연결합니다. B이 아니기 때문에이되고 A이 아닌 const 메서드라고 부를 수 있습니다. 그러나 A이므로A은 다른 B을 가리킬 수 없습니다. B을 회원으로 지정하면 이 아닌 메소드가 A 부분이므로 더 이상 호출 할 수 없습니다.

나는이 문제를 해결할 것 std::unique_ptr를 사용하여 생각하지만 분명히 std::unique_ptrconst를 화살표 연산자 ->에서 const가 아닌 포인터를 반환한다.

template<typename T> 
class const_correct_ptr 
{ 
public: 
    const_correct_ptr(std::unique_ptr<T>): p(std::move(p)) {} 

    // pass constness onto target 
    T* operator->() { return p.get(); } 
    T const* operator->() const { return p.get(); } 

private: 
    std::unique_ptr<T> p; 
}; 

class B 
{ 
public: 
    void nonConstFunction() {} 
}; 

class A 
{ 
public: 
    A(): b(std::make_unique<B>()) {} 

    void someFunc() const 
    { 
     b->nonConstFunction(); // compile time error! 
    } 

private: 
    const_correct_ptr<B> b; 
};