Перед вами короткая программа, в которой демонстрируется использование оператора вывода.

// Использование перегруженного оператора вывода.

#include

using namespace std;

class three_d {

 public:

  int x, y, z; // 3-мерные координаты

  three_d(int a, int b, int с) { x = a; у = b; z = c; }

};

/* Отображение координат X, Y, Z (оператор вывода для класса three_d).

*/

ostream &operator<<(ostream &stream, three_d obj)

{

 stream << obj.x << ", ";

 stream << obj.у << ", ";

 stream << obj.z << "\n";

 return stream; // возвращает параметр stream

}

int main()

{

 three_d a(1, 2, 3), b(3, 4, 5), c(5, 6, 7);

 cout << a << b << c;

 return 0;

}

При выполнении эта программа возвращает следующие результаты:

1, 2, 3

3, 4, 5

5, 6, 7

Если удалить код, относящийся конкретно к классу three_d, останется "скелет", подходящий для любой функции вывода данных.

ostream &operator<<(ostream &stream, class_type obj)

{

 // код, относящийся к конкретному классу

 return stream; // возвращает параметр stream

}

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

Прежде чем переходить к следующему разделу, подумайте, почему функция вывода для класса three_d не была закодирована таким образом.

/* Версия ограниченного применения (использованию не подлежит).

*/

ostream &operator<<(ostream &stream, three_d obj)

{

 cout << obj.x << ", ";

 cout << obj.у << ", ";

 cout << obj.z << "\n";

 return stream; // возвращает параметр stream

}

В этой версии функции жестко закодирован поток cout. Это ограничивает круг ситуаций, в которых ее можно использовать. Помните, что оператор "<<" можно применить к любому потоку и что поток, который использован в "<<"-выражении, передается параметру stream. Следовательно, вы должны передавать функции поток, который корректно работает во всех случаях. Только так можно создать функцию вывода данных, которая подойдет для использования в любых выражениях ввода-вывода.

Использование функций-"друзей" для перегрузки операторов вывода

В предыдущей программе перегруженная функция вывода не была определена как член класса three_d. В действительности ни функция вывода, ни функция ввода не могут быть членами класса. Дело здесь вот в чем. Если операторная функция является членом класса, левый операнд (неявно передаваемый с помощью указателя this) должен быть объектом класса, который сгенерировал обращение к этой операторной функции. И это изменить нельзя. Однако при перегрузке операторов вывода левый операнд должен быть потоком, а правый — объектом класса, данные которого подлежат выводу. Следовательно, перегруженные операторы вывода не могут быть функциями-членами.

В связи с тем, что операторные функции вывода не должны быть членами класса, для которого они определяются, возникает серьезный вопрос: как перегруженный оператор вывода может получить доступ к закрытым элементам класса? В предыдущей программе переменные х, у z были определены как открытые, и поэтому оператор вывода без проблем мог получить к ним доступ. Но ведь сокрытие данных — важная часть объектно-ориентированного программирования, и требовать, чтобы все данные были открытыми, попросту нелогично. Однако существует решение и для этой проблемы: оператор вывода можно сделать "другом" класса. Если функция является "другом" некоторого класса, то она получает легальный доступ к его private-данным. Как можно объявить "другом" класса перегруженную функцию вывода, покажем на примере класса three_d.

// Использование "дружбы" для перегрузки оператора "<<"

#include

using namespace std;

class three_d {

  int x, y, z; // 3-мерные координаты (теперь это private-члены)

 public:

Перейти на страницу:

Все книги серии Изучайте C++ с профессионалами

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