2013-03-09 5 views
2

У меня есть класс с именем A, и в этом классе у меня есть итерируемый контейнер, который я выполняю с помощью следующих правил доступа - порядок, пустота и другие.Утилита итератора класса C++: определение и использование

Для упрощения следующего примера, давайте рассмотрим, я просто итерацию через контейнер, но это не могут быть сделано с помощью итератора в ВСТРАИВАЕМОЙ контейнеры.

class A { 
public: 
    class iterator { 
    public: 
     // Constructor 
     iterator() { 
     } 
     // Destructor 
     ~iterator() { 
     } 
     // Advances the iterator 
     void operator++() { 
      // Some accessing policy 
     } 
    }; 
private: 
    std::vector<int> a; 
}; 

Все работает чрезвычайно хорошо - и выглядит очень аккуратно -, за исключением того, что, когда я заявляю о своем итератор, я должен использовать typename - что я в значительной степени предположить, что используется для того, чтобы сообщить компилятору что у меня есть тип, а не сам класс.

Вопросов:

  1. почему я должен использовать typename, когда я делаю:

    A a; 
    for (typename A::iterator it(...); it != ...; ++it) { 
    } 
    
  2. Как итераторы обычно определяются, так как вектор итератор не требует typename тега ? Это связано с объявлением вектора из определения класса, а не из самого вектора?

    std::vector<int> v; 
    for (std::vector<int>::iterator it(v.begin()); it != v.end(); ++it) { 
    } 
    
  3. ли итераторы, определенные внутри класса контейнера - я предполагаю, что это назвали состав - или, если нет, то как это итераторы добавляются в пространство имен класса, как в:

    std::vector<int>::iterator it; 
    
+0

В 1): Почему вы используете 'a :: iterator' вместо' A :: iterator'? – lucasmrod

+0

@lucasmrod Не уверен; Я предполагаю, что это была моя первая попытка, которую я делаю, потому что я точно не знал, что происходит x = – Rubens

ответ

4

1 - почему я должен использовать typename, когда я делаю: [...]

Вам не нужно использовать typename. Требуется использовать typenameвнутри шаблон, когда вы используете зависимое, квалифицированное имя типа. This Q&A on StackOverflow clarifies things. Это:

A a; 
typename a::iterator it; // ERROR! 

Является ли незаконным C++. При условии, что A не имя параметра шаблона, вы должны просто сделать:

A::iterator it; 

Если вы находитесь внутри шаблона и A это имя параметра шаблона, например, в:

template<typename A> 
struct X 
{ 
    void foo() 
    { 
     typename A::iterator it; 
    // ^^^^^^^^ 
    // This is necessary here! 
    } 
}; 

Затем вы должны использовать typename, чтобы сообщить компилятору, что то, что следует за ::, - это имя типа.


2 - Как итераторы обычно определяется, так как вектор итератор не требует typename тега?

Опять же, это не так, что «вектор итератор не требует typename тега». Если у Вас есть явная специализация этого вектора, например, в:

std::vector<int>::iterator it; // "typename" not required 

typename Тогда не требуется, поскольку это не требуется в A::iterator it. Если вы находитесь внутри шаблона, как в следующем случае, однако, это будет необходимо:

template<typename A> 
struct X 
{ 
    void foo() 
    { 
     typename std::vector<A>::iterator it; 
    // ^^^^^^^^ 
    // This is necessary here! 
    } 
}; 

Это потому, что std::vector<A>::iterator здесь является квалифицированным, зависимым именем типа.


3 - Являются ли итераторы, определенные внутри класса контейнера - я предполагаю, что это назвали состав - или, если нет, то как это итераторы добавляются в пространство имен класса, как и в [ ..]

Это может быть сделано путем определения вложенного класса, или просто сделать с помощью псевдонимов типа:

template<typename T> 
struct X 
{ 
    typedef T* iterator; 
    iterator begin() { /* ... */ } 
    // ... 
}; 

X<int>::iterator it; // OK: "typename" not required 

template<typename T> 
void foo(X<T>& x) 
{ 
    typename X<T>::iterator it = x.begin(); 
// ^^^^^^^^ 
// This is necessary here! 

    // ... 
} 
+0

+1 Whoa! Очень ясно! Теперь я понимаю, почему 'typename' не требуется для' std :: vector :: iterator'. Да, я на самом деле использовал 'template' для' A :: iterator', и я не знал, что 'a :: iterator' был незаконным, так как он в значительной степени работал (: Теперь я предопределю свое определение итератора с помощью объяснение, я делаю итератор DFS, и он выглядит очень аккуратно таким образом ^^ Спасибо за ваш ответ! – Rubens

+0

@Rubens: ОК, рад, что это помогло и удачи :) –

+0

Извините! Я только что проверил, и да, я использовал имя класса, а не экземпляр. У меня было что-то вроде: 'typename Node :: iterator it (...);'. Просто добавив эту информацию, если это может смутить кого-то другого ^^ Ты мне очень помог! (: – Rubens

1

есть много проблем с примерами кода, так что это может быть анс (wave hand) :) Конечно, если ваши примеры неверны, то все ставки отключены.

Я удивлен, что это будет работать вообще. «a» - переменная, «A» - это класс.

Кроме того, при объявлении переменной с конструктором по умолчанию вы не используете конечную скобку().

A a; 
A::iterator it; 
for (A::iterator it; it != ...; ++it) { 
} 

Кроме того, итераторы определены в классе контейнеров. Использование typename должно быть необходимо только тогда, когда вы имеете дело с шаблонами и только при доступе к чему-то, что может быть интерпретировано как статический член или функция/вложенный класс или typedef. Это может быть дополнительно объяснено ответом here, который также дал Энди Проул.

Удача

+0

+1 Мне очень жаль, я должен был сначала ее проверить, на самом деле у меня было «typename A :: iterator it».Я только что обновил его; Спасибо за ваш ответ! – Rubens