Читаем Thinking In C++. Volume 2: Practical Programming полностью

(or in the open( ) member function), and writing happens in the single line (which defaults to sending the output to cout):

file.write();

The bulk of the program is involved with actually modifying the file in memory.

<p>A plethora of iterators</p>

As mentioned earlier in this and the previous chapter, an iterator is an abstraction that allows code to be generic, that is, to work with different types of containers without knowing the underlying structure of those containers. Most containers support iterators.[92] You can always say:.

::iterator

::const_iterator

to produce the types of the iterators produced by that container. Every container has a begin( ) member function that produces an iterator indicating the beginning of the elements in the container, and an end( ) member function that produces an iterator which is the as the past-the-end marker of the container. If the container is const¸ begin( ) and end( ) produce const iterators, which disallow changing the elements pointed to (because the appropriate operators are const).

All iterators can advance within their sequence (via operator++) and allow == and != comparisons. Thus, to move an iterator it forward without running it off the end, you say something like:.

while(it != pastEnd) {

  // Do something

  it++;

}

in which pastEnd is the past-the-end marker produced by the container’s end( ) member function.

An iterator can be used to produce the element that it is currently selecting within a container through the dereferencing operator (operator*). This can take two forms. If it is an iterator and f( ) is a member function of the objects held in the container that the iterator is pointing within, you can say either:.

(*it).f();

or.

it->f();

Knowing this, you can create a template that works with any container. Here, the apply( ) function template calls a member function for every object in the container, using a pointer to member that is passed as an argument:.

//: C07:Apply.cpp

// Using simple iteration

#include

#include

#include

using namespace std;

template

void apply(Cont& c, PtrMemFun f) {

  typename Cont::iterator it = c.begin();

  while(it != c.end()) {

    ((*it).*f)(); // Alternate form

    it++;

  }

}

class Z {

  int i;

public:

  Z(int ii) : i(ii) {}

  void g() { i++; }

  friend ostream&

  operator<<(ostream& os, const Z& z) {

    return os << z.i;

  }

};

int main() {

  ostream_iterator out(cout, " ");

  vector vz;

  for(int i = 0; i < 10; i++)

    vz.push_back(Z(i));

  copy(vz.begin(), vz.end(), out);

  cout << endl;

  apply(vz, &Z::g);

  copy(vz.begin(), vz.end(), out);

} ///:~

You can’t use operator-> in this case, because the resulting statement would be

(it->*f)();

which attempts to use the iterator’s operator->*, which is not provided by the iterator classes.[93]

It is much easier to use either for_each( ) or transform( ) to apply functions to sequences anyway, as you saw in the previous chapter.

<p>Iterators in reversible containers</p>

A container may also be reversible, which means that it can produce iterators that move backward from the end, as well as the iterators that move forward from the beginning. All standard containers support such bidirectional iteration.

A reversible container has the member functions rbegin( ) (to produce a reverse_iterator selecting the end) and rend( ) (to produce a reverse_iterator indicating "one past the beginning"). If the container is const, rbegin( ) and rend( ) will produce const_reverse_iterators.

The following example uses vector, but will work with all containers that support iteration:

//: C07:Reversible.cpp

// Using reversible containers

#include

#include

#include

#include

#include "../require.h"

using namespace std;

int main() {

  ifstream in("Reversible.cpp");

  assure(in, "Reversible.cpp");

  string line;

  vector lines;

  while(getline(in, line))

    lines.push_back(line);

  for(vector::reverse_iterator r = lines.rbegin();

      r != lines.rend(); r++)

    cout << *r << endl;

} ///:~

You move backward through the container using the same syntax as moving forward through a container with an ordinary iterator.

<p>Iterator categories</p>

The iterators are classified into "categories" that describe their capabilities. The order in which they are generally described moves from the categories with the most restricted behavior to those with the most powerful behavior.

<p>Input: read-only, one pass</p>
Перейти на страницу:

Похожие книги

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

Программирование, программы, базы данных / Программное обеспечение / Книги по IT