Перед вами короткая программа, в которой демонстрируется использование оператора вывода.
// Использование перегруженного оператора вывода.
#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: