Menu
Coddy logo textTech

Операторы потоков

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 43 из 104.

Операторы вставки в поток (<<) и извлечения из потока (>>) позволяют использовать ваши пользовательские классы с std::cout и std::cin. В отличие от операторов, которые мы рассматривали до сих пор, они должны быть реализованы как функции, не являющиеся членами класса, поскольку левый операнд является потоком, а не вашим классом.

class Point {
    int x, y;
    
public:
    Point(int x, int y) : x(x), y(y) {}
    
    // Объявите как friend для доступа к закрытым членам
    friend std::ostream& operator<<(std::ostream& os, const Point& p);
    friend std::istream& operator>>(std::istream& is, Point& p);
};

std::ostream& operator<<(std::ostream& os, const Point& p) {
    os << "(" << p.x << ", " << p.y << ")";
    return os;
}

std::istream& operator>>(std::istream& is, Point& p) {
    is >> p.x >> p.y;
    return is;
}

Оба оператора возвращают ссылку на поток, что позволяет выстраивать цепочки, такие как std::cout << p1 << p2. Оператор вставки принимает объект по const ссылке, так как он только считывает данные, в то время как оператор извлечения принимает неконстантную ссылку, так как он изменяет объект.

Теперь вы можете использовать Point естественным образом с потоками:

Point p(3, 4);
std::cout << "Location: " << p << std::endl;    // Вывод: Location: (3, 4)

Point p2(0, 0);
std::cin >> p2;    // Чтение двух целых чисел в p2
challenge icon

Задание

Легко

Давайте создадим класс Temperature, который можно будет легко использовать с std::cout и std::cin с помощью перегрузки операторов потока. Это практический сценарий, когда вы хотите отображать температуру в читаемом формате и считывать её из входных данных естественным образом.

Вы создадите два файла для организации своего кода:

  • Temperature.h: Определите класс Temperature, который хранит значение в градусах Цельсия (как double) и метку единицы измерения (как char, либо 'C' для Цельсия, либо 'F' для Фаренгейта). Ваш класс должен иметь:
    • Приватные члены для значения температуры и единицы измерения
    • Конструктор по умолчанию, который инициализирует значение 0.0 градусов Цельсия
    • Параметризованный конструктор, принимающий значение и единицу измерения
    • Геттеры getValue() и getUnit() (оба const)
    • Дружественные объявления (friend) для операторов вставки в поток (<<) и извлечения из потока (>>)

    Реализуйте операторы потока как функции, не являющиеся членами класса:

    • Оператор вставки должен выводить температуру в формате VALUE UNIT (например, 25.5 C или 77.9 F). Используйте один десятичный знак для значения.
    • Оператор извлечения должен считывать значение и символ единицы измерения из потока и сохранять их в объекте Temperature.

    Оба оператора должны возвращать ссылку на поток для обеспечения возможности цепочки вызовов.

  • main.cpp: Считайте две температуры из входных данных. Каждая температура указывается в отдельной строке в формате value unit (например, 25.5 C).

    Создайте два объекта Temperature, используя оператор извлечения для их чтения из std::cin. Затем выведите их с помощью оператора вставки в следующем формате:

    Temperature 1: <temp1>
    Temperature 2: <temp2>

    Например, если входные данные:

    25.5 C
    98.6 F

    Выходные данные должны быть:

    Temperature 1: 25.5 C
    Temperature 2: 98.6 F

Используйте std::fixed и std::setprecision(1) из <iomanip>, чтобы отформатировать значение температуры ровно с одним десятичным знаком. Не забудьте про include guards (защиту заголовков) в вашем заголовочном файле.

Шпаргалка

Операторы вставки в поток (<<) и извлечения из потока (>>) позволяют пользовательским классам работать с std::cout и std::cin. Эти операторы должны быть реализованы как функции, не являющиеся членами класса, так как левым операндом является объект потока, а не ваш класс.

Базовый синтаксис

class Point {
    int x, y;
    
public:
    Point(int x, int y) : x(x), y(y) {}
    
    // Объявите как friend для доступа к приватным членам
    friend std::ostream& operator<<(std::ostream& os, const Point& p);
    friend std::istream& operator>>(std::istream& is, Point& p);
};

std::ostream& operator<<(std::ostream& os, const Point& p) {
    os << "(" << p.x << ", " << p.y << ")";
    return os;
}

std::istream& operator>>(std::istream& is, Point& p) {
    is >> p.x >> p.y;
    return is;
}

Ключевые моменты

  • Оба оператора возвращают ссылку на поток для обеспечения возможности цепочки вызовов (например, std::cout << p1 << p2)
  • Оператор вставки (<<) принимает объект по константной ссылке (const reference), так как он только считывает данные
  • Оператор извлечения (>>) принимает неконстантную ссылку, так как он изменяет объект
  • Используйте объявления friend, чтобы позволить этим функциям, не являющимся членами класса, обращаться к приватным членам

Пример использования

Point p(3, 4);
std::cout << "Location: " << p << std::endl;    // Вывод: Location: (3, 4)

Point p2(0, 0);
std::cin >> p2;    // Считывание двух целых чисел в p2

Попробуйте сами

#include <iostream>
#include "Temperature.h"

int main() {
    // TODO: Создайте два объекта Temperature
    
    // TODO: Используйте оператор извлечения (>>) для чтения двух температур из std::cin
    
    // TODO: Выведите температуры, используя оператор вставки (<<)
    // Формат:
    // Temperature 1: <temp1>
    // Temperature 2: <temp2>
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование