2010-12-18 6 views
4

내 자신의 LinkedList 클래스 버전을 구현하려하고 있으며 상수 iterator에 대한 오버로드 메서드에 문제가 있습니다. 나는 이러한 오류가C++ : 상수 iterator에 대한 list.end() 및 list.begin() 메서드 오버로드

cout << "citer:" << endl; 
for (UberList<int>::CIter it = ulist.begin(); it != ulist.end(); ++it) 
{ 
cout << *it << " "; 
} 
cout << endl; 

: 예를 들어,이 코드를 사용하여 목록을 인쇄 할 때 지금까지 내가 이해로

Error E2034 UberList2.cpp 532: Cannot convert 'UberList<int>::Iter' to 'UberList<int>::CIter' in function main() 
Error E2094 UberList2.cpp 532: 'operator!=' not implemented in type 'UberList<int>::CIter' for arguments of type 'UberList<int>::Iter' in function main() 

를, 그것은 그 보통의 끝이 반복자 방법을 시작하는 것을 의미한다 사용됩니다. 여기에 이러한 방법은 내 수업에 선언하는 방법은 다음과 같습니다

Iter begin(); 
Iter end(); 
CIter begin() const; 
CIter end() const; 

template<class T> 
typename UberList<T>::Iter UberList<T>::begin() 
{ 
    Iter it; 
    it.curr = head; 
    return it; 
} 

template<class T> 
typename UberList<T>::Iter UberList<T>::end() 
{ 
Iter it; 
it.curr = tail->next; 
return it; 
} 

template<class T> 
typename UberList<T>::CIter UberList<T>::begin() const 
{ 
CIter it; 
it.ccurr = head; 
return it; 
} 

template<class T> 
typename UberList<T>::CIter UberList<T>::end() const 
{ 
CIter it; 
it.ccurr = tail->next; 
return it; 
} 

내가 대신 보통 사람의 상수 반복자 이러한 CONST 방법을 사용하여 내 프로그램을 강제 할 수있는 방법이 있나요를? 나는 조언을 듣게되어 기뻐. 여기

아, 그리고는 경우 하나 개의 파일 내 클래스의 코드입니다 : http://pastebin.com/Jbvv5Hht

+0

코드가 괜찮아 보입니다. pastebin의 연산자에 'const'가 추가되었습니다. 아마도 도움이되지는 않지만 코드는 정상적으로 보입니다. – Drakosha

+0

감사합니다.하지만이 오류는 여전히 발생합니다. ( – Chris

답변

7

당신은 Iter에서 CIter에 변환을 제공해야한다. 표준 컨테이너가 할 (23.1 "컨테이너 요구 사항"표 65, X::iteratorX::const_iterator로 변환 것을 말한다)

호출자가 const 과부하가 const 참조를 사용하여 호출되도록 할 수 있습니다,하지만 당신은 그들을 강요해서는 안 그것을 위해하는 것처럼, 원래의 코드가 작동합니다

UberList<int>::CIter it = static_cast<const UberList<int> &>(ulist).begin() 

는 "필수"변환을 제공하는 경우 발신자가 특별한 아무것도 할 필요가 없습니다 : 그들은 뭔가를 작성해야하기 때문에, 그렇게 표준 컨테이너.

+0

음,하지만 CIter 유형을 반환하고 변환을 피하는 시작과 끝 방법을 사용하도록 할 수 있습니까? – Chris

+0

@Chris : 당신은합니까? "컨테이너를 쓰는 사람"또는 "컨테이너를 사용하는 코드를 작성하는 사람"과 같은 "나"를 의미합니다. 후자는 예, 아니오는 이전을 의미합니다. 컨테이너 인터페이스를 사용하는 표준? –

+0

왜냐하면 내가 정말 어떻게 변환을 구현할 수 있는지 모르겠지만 .Iter 및 CIter Iter 및 CIter 가져 오기 링크를받는 CIter 생성자를 만들었습니다 = 및 CIter - 연산자를 반복하지만 여전히 같은 오류 메시지가 나타납니다. – Chris

0

당신은 변수가 const를하지 않기 때문에 일반이 방법을 시작 사용하고

teamplate<class T> bool operator!=(UberList<T>::CIter,UberList<T>::CIter); 
+0

을 원하는대로 작동 감사합니다 :.이 컴파일러는 두 번째 오류 메시지에 대해 불평 것입니다 – Chris

+0

아니지만 그것이 있어야 –

-2

이 필요합니다. 따라서 수정하는 한 가지 방법은 다른 변수 (참조)를 const로 만드는 것입니다.

UberList<int> const & culist = ulist; 
for (UberList<int>::Citer it = culist.begin(); ...) 

또는 const_cast를 사용하십시오.

+0

당신은 필요가 없습니다 const를 추가하기 위해'const_cast'를 사용하지 말아야합니다. –

+0

물론 const를 추가하려면 const_cast를 사용해야합니다. 그게 요점입니다. 대신에 static_cast를 사용하면 바람직하지 않게 잘못된 캐스트를 수행 할 수 있습니다. 컴파일러가 수행하는 유일한 변환은 const (또는 휘발성)의 추가 또는 제거라는 것입니다. –

+1

'const_cast'의 "전체 점"은 const를 제거 할 수있는 유일한 캐스트입니다. 그러나 그렇다면 당신의 컨테이너가 변환 될 수있는 다른 타입이 존재할 때, 컴파일러가 당신이 그 중 하나로 변환하지 않는다는 것을 확인하는 것은 이론적으로 유용하다. 물론 당신이 말하는 것처럼, const_cast를 사용하면 const를 추가하는 것과 동시에 volatile을 실수로 제거합니다. 이는 아마도 const를 추가하기 위해 const_cast를 사용하지 않는 주된 이유 일 것입니다. 컴파일러가 어떤 오류를 잡을 지 결정합니다. 에 const_cast 물건이 나 –

1

OP의 코드에 대한 코멘트가 더 있습니다. 거대한 uberl33tlist 클래스를 분리하여 작은 파일로 분리하십시오. 그 모든 친구들의 클래스 선언을 보는 것은 나를 다소 불편하게 만듭니다. 당신은 그들이 아직 존재하지 않는 경우 어떤 경우에는 그 문은 또한 앞으로 해당 클래스를 선언 을 끝낼

friend class UberList; 
friend class CIter; 

같은 물건을 사용할 때 몇 가지 까다로운 의미도 있습니다. 확실히 여기 당신의 할당 연산자에 대해보고 있지 뭔가도 있습니다 :

당신은 당신은 IT2에 대한 후위 연산자 ++를 사용하고 있지만, 구현하지 않았다

it2++; 
ulist.insertAfter(b, it2); 
//... 

이 주에서 또한

UberList<T> operator = (const UberList<T>& OL) 
{ 
    UberList<T> NL = new (OL); 
    return NL; 
} 

당신의 반복자 클래스.Borland는 대신 접두어를 사용하여이를 허용하지만 경고를 표시합니다. Gcc는 사실이를 오류로 표시하고 코드를 거부합니다. 그걸 살펴보고 싶을 수도 있습니다

+0

확인, 감사합니다 :) 당신은 음 흥미 – Chris

1

한숨 : 여기에는 개념적으로 원하는 것을 개념적으로 숨기도록 설계된 해커 수준이 있습니다. 분산을 이해하지 못하기 때문에 C++에서는 자동으로 수행 할 수 없습니다. 일부 다른 언어 (Ocaml 포함)가 있습니다.

Functor (C++ 프로그래머에게 제공되는 템플릿 클래스)를 사용하는 경우 문제는 다양한 함수가 T에서 T const 로의 변환과 같이 매개 변수의 분산으로 어떻게 작용하는지입니다. 당신이 정말로 원하는 것은 다음과 같습니다 :

List<T> --> List<T const> 

즉, List Functor가 공변수가되기를 원합니다. 그러나 아니요, 실제로는 List 템플릿은 펑터가 아닙니다. 펑터는 구조를 유지해야하며 필요에 따라 변환이 반영되지 않습니다. 이는 매개 변수 다형성을 지원하지 않는 유형 시스템이 사양에 의해 손상 되었기 때문에 C++ 템플릿이 손상되었거나 const의 개념이 손상되었음을 의미합니다.

"const_iterator"를 제공하면이 문제가 해결되지 않으며 간단하게 휴식 시간에 패치. 휘발성 및 const_volatile 버전은 어디에 있습니까? 어때?

당신이 이중 indirections을 이해하지 않는 경우 :

Tree<Vector<T>> 

여기에 가장 좋은 방법은 const_iterator를 지원 포기하는 것입니다 : T의 벡터의 나무 생각, 즉 두 개의 템플릿입니다. 귀찮게하지 마라. 그것은 어쨌든 혼란 스럽습니다 : "const vector"는 어떻습니까? 그게 뭐야? 더 길게 만들 수는 없지만 여전히 요소를 쓸 수있게 해주는 벡터?

vector<T> const == vector<T const> 

[하거나 변환 금기 변형 경우 안티 통근]

이 사실이 발생하지 않는 프로그램이 벡터 :

실제 요구는 예를 들면, 통근 변환이고 즉, 템플릿은 매개 변수 다형성에 효과적으로 사용할 수 없습니다. knickers를 매듭에 묶고 싶다면 함수 인자가있는 템플릿을 고려하고 함수의 리턴 타입과 매개 변수의 차이점과 이것이 컨테이너에 미치는 영향에 대해 물어보십시오. 좋은 예는 쌍으로 작업 할 수 있도록 두 가지 함수를 작성하는 방법입니다. 만약 그들이 돌연변이라면 어떻게 "const"가 작동할까요?

+0

를 adviced로 내 코드를 변경합니다 – Chris