2012-01-12 2 views
6

내 문제는 간단합니다. 나는 동적으로 할당 된 타입에 대한 포인터를 가지고있는 클래스 템플릿을 가지고있다. 간접 연산자를 오버로드하여 -> 연산자를 사용하여 클래스 템플릿 인스턴스를 참조하면 직접 포함 된 포인터를 사용하는 것처럼 리디렉션됩니다.C에서 간접 연산자를 오버로드

instance.ptr->someMemberMethod(); 

단순히 입력 : 심지어

intance->someMemberMethod(); 

MyClass<SomeObject> instance; 

그래서 내가 원하는 것은 대신 입력 할 필요하다 :

template<class T> 
class MyClass 
{ 
    T *ptr; 
    ... 
    // created dynamic resource for ptr in the constructor 
}; 

어떤 종류의 MyClass에 만들기 너 instance은 ap가 아니다. ointer 포인터가 마치 instance에있는 것처럼 작동합니다. 운영자 과부하로 그 격차를 해소하는 방법은 무엇입니까?

template<class T> 
class MyClass 
{ 
    T* ptr; 

public: 
    T* operator->() { 
     return ptr; 
    } 

    // const version, returns a pointer-to-const instead of just a pointer to 
    // enforce the idea of the logical constness of this object 
    const T* operator->() const { 
     return ptr; 
    } 

    T& operator*() { 
     return *ptr; 
    } 

    // const version, returns a const reference instead of just a reference 
    // to enforce the idea of the logical constness of this object 
    const T& operator*() const { 
     return *ptr; 
    } 
}; 

참고로 인해 언어의 창조자에 의해 디자인 결정, 당신은 . 연산자를 오버로드 할 수 없습니다 :

+0

현대 C + + 디자인 (Andrei Alexandrescu) 당신이 더 깊이 싶으면 피사체에 대한 좋은 정보가 있습니다. –

답변

11

당신은 operator->operator*를 오버로드 할 수 있습니다.

또한 operator*은 역 참조 연산자 대신 연산자 인 연산자를 오버로드한다고 생각할 수 있습니다. 그러나, 곱셈 연산자가 하나의 인수를 취하고 (비 참조 연산자가 인수를 취하지 않기 때문에), 컴파일러는 어떤 연산자인지 알 수 있기 때문에 그렇지 않습니다.

마지막으로 operator->은 포인터를 반환하지만 operator*은 참조를 반환합니다. 우연히 그들을 혼동시키는 것은 쉽습니다.

+0

좋은 답변입니다. 하지만 const 버전과 non-const 버전의 차이점을 말씀해 주시겠습니까? 언제 내가 그 중 하나를 사용합니까? – SimpleGuy

+0

왜'->'와'*'를 오버로드해야하는지. '->'과부하 만하는 이유는 무엇입니까? – SimpleGuy

+0

@SimpleGuy 클래스의 사용자는 일반적으로'foo-> bar'가'(* foo) .bar'와 같을 것으로 기대합니다. 서로 다르다면 많은 사람들이 충격을받을 것입니다. – Bernard

5

에 과부하 -> 운영자 : 모두 과부하 개체를 변이하지 않는

template <typename T> class MyClass 
{ 
    T * p; 
public: 
    T  * operator->()  { return p; } // #1 
    T const * operator->() const { return p; } 
}; 

것을; 그럼에도 불구하고 우리는 # 1 non-const를 만들기로 결심한다. 그래서 우리는 pointee에 객체의 constence를 유지한다. 이것은 때로는 "깊이있는 전파"또는 이와 비슷한 것입니다. 언어 D는 이것을 훨씬 더 많이 사용합니다.

+0

"우리는 # 1 비 - const"를 만들기로 결심한다 - 적어도, 우리는 원한다면 할 수있다. 표준 스마트 포인터는 본질적으로 동일한 이유 때문에'T * const'를 통해 'T'유형의 객체를 수정할 수 있습니다. 당신이하는 일은'instance'가 "논리적으로"다른 객체에 대한 간접 참조 (표준 스마트 포인터를 모방)인지 아닌지 (Bjarne를 저주하면'operator.'를 오버로드 할 수 없음)에 따라 다릅니다. –

+1

@SteveJessop : "우리는 모든 의견의 현존하는 통치자"라기보다는 "당신과 나는 C++ 로의 여행"에서와 같이 "우리"라고 생각합니다. 죄송합니다, 오래된 습관 :-) –

3

멤버 액세스 연산자에 액세스 할 수있는 객체에 대한 포인터를 반환하는 오버로드 할 수 있습니다 : 당신은 또한 존중 연산자를 할 수 있습니다

T * operator->() {return ptr;} 
T const * operator->() const {return ptr;} 

, 그것은 더 포인터처럼 느낄 수 있도록; 이 대신 참조를 반환합니다 :

T & operator*() {return *ptr;} 
T const & operator*() const {return *ptr;} 
관련 문제