2013-02-21 3 views
1

나는 더 똑똑한 포인터 클래스를 작성했습니다. 그리고 올바른 다음 코드를 만들기 위해오버로드 연산자! =

이 같은 = 연산자 오버로드
ZhjSmartPointer<int> a(new int); 
assert(a != NULL); 

:

ZhjSmartPointer.h이 같은 컴파일 오류에

bool operator !=(T *ptr) const; 

그러나,이 리드를! : 132 : 참고 : 후보 1 : bool ZhjSmartPointer :: operator! = (T *) const [T = Test와 함께] test.cpp : 41 : 참고 : 후보 2 : 연산자! = (int, int)

나는 ZhjSmartPointerint

로 옮겨진 할 수있는 방법을 혼동 해요 SmartPointer 클래스의 코드는 다음과 같다 :

나는 '부울'연산자를 오버로드 때문에 추측
template <typename T> 
class ZhjSmartPointer { 
public: 
    ZhjSmartPointer(); 
    explicit ZhjSmartPointer(T *ptr); 

    ZhjSmartPointer(const ZhjSmartPointer &smartPtr); 
    ZhjSmartPointer &operator =(const ZhjSmartPointer &smartPtr); 
    ~ZhjSmartPointer(); 

    operator bool() const; 
    T &operator *() const; 
    T *operator ->() const; 
    bool operator ==(const ZhjSmartPointer &smartPtr) const; 
    bool operator !=(const ZhjSmartPointer &smartPtr) const; 

    bool operator ==(T *ptr) const; 
    bool operator !=(T *ptr) const; 

private: 
    void copyPtr(const ZhjSmartPointer &smartPtr); 
    void deletePtr(); 
    T *ptr_; 
    size_t *refCnt_; 
}; 

, 'ZhjSmartPointer -> bool -> int'로하면이 문제가 발생합니다. 맞습니까?

죄송 합니다만, 이것은 단지 컴파일 경고 일 뿐이며 오류는 아닙니다. 누군가 오버로드하지 말 것을 제안합니다! = 매개 변수 (T *)로, 결국 우리는 'bool'을 오버로드했습니다. 다음과 같은 코드를 작성하면됩니다.
ZhjSmartPointer a (new int);
(A) { ..........
} NULL ++ C에서

+1

'명시 적'이 아닌 매개 변수로 'int'를 사용하는 생성자가 해당 변환을 유발할 수 있습니다. – phoeagon

+0

생성자는'int' (잘 T)가 아니라'int *'(T *)를 취할 것이므로 "암시 적 생성자 변환"이 존재하지 않는다는 것은별로 의미가 없습니다. 'ZhjSmartPointer '에서'int'로 암시 적 변환을 허용하여이 오류를 유발할 수 있다는 가정은 의미가 있습니다. 'intptr'을 사용하거나 암시 적 변환을 제거하는 것 외에는 할 수있는 일이별로 없습니다. – Voo

+0

아래 답변에서 말했듯이'g ++ 4.6.3'에서 경고 메시지와 함께 작동합니다. 그래서 컴파일러에 의존하는 것 같아요. 당신의 컴파일러는 무엇입니까? – phoeagon

답변

0

'bool'연산자가 과부하 되었기 때문에 'ZhjSmartPointer -> bool -> int'로이 문제가 발생합니다. 맞습니까?

나는 그렇게 생각합니다.

그러나 ZhjSmartPointer에 대한 변환 연산자를 정의 했습니까?

#include <cassert> 
#include <cstddef> 

template <class T> 
class ZhjSmartPointer{ 
    public: 
    ZhjSmartPointer (T* _ptr) 
    :ptr_saved(_ptr){ } 
    bool operator !=(T *ptr) const{ 
     return ptr!=ptr_saved; 
    } 
    private: 
    T* ptr_saved; 
}; 
int main(){ 
    ZhjSmartPointer<int> a(new int); 
    assert(a != NULL);  
} 

이것은 (g++ 4.6.3)로 컴파일됩니다.

operator bool() const{ 
     return ptr_saved!=0; 
    } 

g++ 4.6.3경고를 발행하지만 여전히 컴파일 : 추가.

1.cpp:9:14: Candidate 1: bool ZhjSmartPointer<T>::operator!=(T*) const [with T = int] 
1.cpp:20:9: Candidate 2: operator!=(int, int) <builtin> 

사용되지 놀랍게도NULLint 아닌 void*이다.

선언 생성자처럼 :

ZhjSmartPointer<int> a(new int); 

ZhjSmartPointer에 INT의 변환을 할 수 있습니다. 대신이 전환을 억제하려면 explicit :

explicit ZhjSmartPointer<int> a(new int); 

을 추가하십시오.

+2

전 (또는 후자) 생성자 선언 *은 어떨까요? 내가보기에 변수 * 선언 만 있습니다. 사실 * 명시 적 *은 비 정적 멤버 함수에만 나타날 수 있습니다. 위의 스 니펫은 컴파일되지 않습니다. – WhozCraig

1

는 사실, 0하지 (void*)0로 정의되면 대부분의 교과서 대신 NULL0를 사용하라고 알려 줄 것입니다.

당신이 방법


귀하의 문제 nullptr를 사용한다 C++ (11)를 사용하는 경우는 실제로 bool 암시 적 변환입니다. 대신 문제가있는 오버로드 연산자 (!)를 수정하십시오.

+1

C++ 11에서는 'nullptr'이 '0'과 다른 유형입니다. 'NULL'과'0'은 의미 상으로는 다르며 동등하다는 사실에 의존하는 것은 나쁜 습관입니다. 그래서 "대부분의 교과서"에는 나쁜 조언이 포함되어 있습니다. – congusbongus

+0

@CongXu 아니요, NULL과'0'은 C++에서 의미 상으로는 똑같은 것입니다. 이 사실에 의지하는 것은 완벽합니다 ("하드웨어가 널 포인터를 다르게 표현한다면 어떨까요?"라고 말할 수 있습니다. "표준에서는 컴파일러가 올바르게 변환해야한다고 말합니다."). 나는이 사실을 좋아하지 않는다.'nullptr'은 좋다. – Voo

+0

@Voo "의미상으로"나는 프로그래머와 관련하여, 즉, 포인터가 NULL이고 숫자가 숫자 인 경우 0을 사용해야한다는 것을 의미합니다. 언어와 관련해서는 다른 방향입니다. 혼란을 드려 죄송합니다. – congusbongus