2012-07-04 2 views
0

필자의 이해는 typedef가 유형의 동의어로 사용되거나 특정 유형의 별칭으로 사용될 수 있습니다. 또한, 아래의 간단한 코드는 완벽하게 구축되었습니다.typedef 동의어 대체

Array<int>::ArrayIter<T> pa = a.begin(); // substituting back the typedef “iterator” to its original form of ArrayIter<T>. 

내가 컴파일하는 동안 다음과 같은 오류 메시지가 얻을 :

"ArrayIter"는 "배열"

의 구성원이 아닌 내가 메인 함수에서 두 번째 줄을 변경하는 경우 여기에 문제는

그러나 코드는 "typedef"(반복기) 표기법을 사용하여 완벽하게 컴파일됩니다. 왜 "반복자"이고 ArrayIter 갑자기 동의어하지 더 이상 아래

참조 코드 :

template<class T> class ArrayIter { 
public: 
ArrayIter(T* p) : m_p(p) { 
} 

private: 
T* m_p; 
}; 

template<class T> class Array { 

public: 
    Array(int size) throw (const char*) { 
    if (size > 0) { 
     m_p = new T[size]; 
     m_size = size; 
    } else { 
    throw "Array: invalid array dimension"; 
} 
    } 

    // typedef and methods to support the new iterator for this class 
    typedef ArrayIter<T> iterator; 

    ArrayIter<T> begin() { 
    return ArrayIter<T>(m_p); 
    } 

private: 
    T* m_p; 
    int m_size; 
}; 


int main(int argc, char* argv[]) { 

    Array<int> a(10); 
    Array<int>::iterator pa = a.begin(); 

return 0; 
} 

답변

1

와 동일 ArrayIter가 아니다 member of Array : 주변 클래스 네임 스페이스에 선언 된 별도의 클래스입니다. 따라서 Array<int>::ArrayIter<T>은 유효하지 않으며 단지 ArrayIter<int>이어야합니다.

iteratorArray의 부재이므로 Array<int>::iterator유효하며, ArrayIter<int> 별명이다.

+0

마이크에게 모든 대답을 해주셔서 감사합니다. 나는 새로운 회원이며 정말로이 사이트를 많이 평가했습니다. 고마워요! –

0

ArrayIter 그렇게 Array::ArrayIter가 무효 선언 될 Array 내부 중첩 클래스가 아닙니다. ArrayIter은 전역 범위에서만 정의되므로 ArrayIter<int> iter = a.begin(); 수 있습니다. typedef iteratorArray에 정의되어 있으므로 Array<int>::iterator으로 액세스 할 수 있습니다.

0

ArrayIter<T> 분명히 Array의 멤버가 아닙니다. 외부에 선언되었을 때 어떻게 될 수 있습니까?

이해의 차이는 범위 지정 작동 방식입니다.

class A 
{ 
}; 

A은 이제 전역 이름 공간에 입력됩니다.

class B 
{ 
public: 
    typedef ::A C; 
}; 

CB의 내부에 정의된다, 그래서 이름이 B::C입니다입니다 : 자, 두 번째 클래스를 가정하자. 그러나 A은 여전히 ​​글로벌 네임 스페이스에 있습니다! typedef 뭔가를 입력해도 원래 이름의 범위가 변경되지 않으므로 A은 절대로 B의 구성원 일 수 없습니다.

는 결론적으로 - 글로벌 네임 스페이스에서가 (코드에서 가져온) 다음과 같다 : 오류가 말한대로

Array<int>::iterator pa = a.begin(); 

ArrayIter<int> pa = a.begin(); 
+0

당신 해명 주셔서 대단히 Griwes 감사 놓아야합니다. –

0

변종 간의 동등성이 보이지 않습니다. ArrayIter은 유형이 아니며 템플릿입니다. 귀하의 예에서 typedef 이름 iterator은 특정 전문 ArrayIter 템플릿을 나타냅니다.Array<int> 내부는 ArrayIter<int>을 나타냅니다. Array<double> 안에는 ArrayIter<double>을 참조 할 것입니다. 이것은 정확하게 컴파일러에게 typedef으로 요청한 것입니다.

어떤 식 으로든 ArrayIter 템플릿을 Array 클래스로 가져 오지는 않습니다. 아직 회원이 아닙니다. Array<>::iterator은 단순히 그것을 참조하는 반면에 그것은 여전히 ​​글로벌 네임 스페이스에 있습니다.

무엇보다 main을 참조하려는 것이 명확하지 않습니다. 거기에는 T이 없습니다.

템플릿으로 ArrayArrayIter을 가지고 싶은 경우에, 당신은 지금 "템플릿 형식 정의"또는 "템플릿 별칭 선언"

template <typename T> 
class Array { 
    ... 
    template <typename U> using ArrayIter = ::ArrayIter<U>; 
    ... 
}; 

로 알려진 C++ 11 표준의 새로운 기능을 사용 할 수 있습니다 Array::ArrayIter을 템플릿으로 사용할 수 있습니다.

0

음, typedef를 "실행 취소"하고 싶다고하셨습니다.

배열 [INT] 내에서 사용될
typedef ArrayIter<T> iterator; 

는 광고

Array<int>::iterator pa = a.begin(); 

주어진

그래서
typedef ArrayIter<int> iterator; 

이 "팽창"은 상기 타입 정의를 사용한다 : 당신의 타입 정의는 다음과 같다 가져 오기 위해 수동으로 typedef를 실행 취소 할 수 있습니다.

ArrayIter<int> pa = a.begin(); 

잘 작동합니다 :-)

기본적으로 typedef의 이름은 "iterator"가 아니라 "Array [int] :: iterator"입니다.

0

귀하의 이터레이터는 Array의 범위에 정의되어 있고 ArrayIter은 전역 범위에 정의되어 있기 때문입니다. 당신이 말을 달성하기 위해, 당신은 ArrayIterArray 내부

template<class T> class Array { 

public: 
    template<class T> class ArrayIter { 
    public: 
     ArrayIter(T* p) : m_p(p) { 
     } 

    private: 
     T* m_p; 
    }; 


    Array(int size) throw (const char*) { 
     if (size > 0) { 
      m_p = new T[size]; 
      m_size = size; 
     } else { 
      throw "Array: invalid array dimension"; 
     } 
    } 

    // typedef and methods to support the new iterator for this class 
    typedef ArrayIter<T> iterator; 

    ArrayIter<T> begin() { 
     return ArrayIter<T>(m_p); 
    } 

private: 
    T* m_p; 
    int m_size; 
}; 


int main(int argc, char* argv[]) { 

    Array<int> a(10); 
    Array<int>::ArrayIter<int> pa = a.begin(); 

    return 0; 
}