Menu
Coddy logo textTech

Operadores de flujo (Stream)

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 43 de 104.

Los operadores de inserción (<<) y extracción (>>) de flujo le permiten usar sus clases personalizadas con std::cout y std::cin. A diferencia de los operadores que hemos cubierto hasta ahora, estos deben implementarse como funciones no miembro porque el operando izquierdo es un flujo, no su clase.

class Point {
    int x, y;
    
public:
    Point(int x, int y) : x(x), y(y) {}
    
    // Declarar como friend para acceder a los miembros privados
    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;
}

Ambos operadores devuelven una referencia al flujo, permitiendo el encadenamiento como std::cout << p1 << p2. El operador de inserción toma el objeto por referencia const ya que solo lee datos, mientras que la extracción toma una referencia no constante porque modifica el objeto.

Ahora puedes usar Point naturalmente con streams:

Point p(3, 4);
std::cout << "Location: " << p << std::endl;    // Salida: Location: (3, 4)

Point p2(0, 0);
std::cin >> p2;    // Lee dos enteros en p2
challenge icon

Desafío

Fácil

Vamos a construir una clase Temperature que se pueda utilizar sin problemas con std::cout y std::cin a través de la sobrecarga de operadores de flujo. Este es un escenario práctico en el que deseas mostrar temperaturas en un formato legible y leerlas de la entrada de forma natural.

Crearás dos archivos para organizar tu código:

  • Temperature.h: Define una clase Temperature que almacene un valor en Celsius (como un double) y una etiqueta de unidad (como un char, ya sea 'C' para Celsius o 'F' para Fahrenheit). Tu clase debe tener:
    • Miembros privados para el valor de la temperatura y la unidad
    • Un constructor por defecto que inicialice a 0.0 Celsius
    • Un constructor parametrizado que reciba un valor y una unidad
    • Getters getValue() y getUnit() (ambos const)
    • Declaraciones de amistad (friend) para los operadores de inserción de flujo (<<) y extracción (>>)

    Implementa los operadores de flujo como funciones que no son miembros:

    • El operador de inserción debe mostrar la temperatura en el formato VALUE UNIT (por ejemplo, 25.5 C o 77.9 F). Usa un lugar decimal para el valor.
    • El operador de extracción debe leer un valor y un carácter de unidad del flujo y almacenarlos en el objeto Temperature.

    Ambos operadores deben devolver una referencia al flujo para permitir el encadenamiento.

  • main.cpp: Lee dos temperaturas de la entrada. Cada temperatura se proporciona en una línea separada en el formato value unit (por ejemplo, 25.5 C).

    Crea dos objetos Temperature utilizando el operador de extracción para leerlos de std::cin. Luego, muéstralos usando el operador de inserción en este formato:

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

    Por ejemplo, si la entrada es:

    25.5 C
    98.6 F

    La salida debe ser:

    Temperature 1: 25.5 C
    Temperature 2: 98.6 F

Usa std::fixed y std::setprecision(1) de <iomanip> para formatear el valor de la temperatura con exactamente un lugar decimal. No olvides los protectores de encabezado (header guards) en tu archivo de cabecera.

Hoja de referencia

Los operadores de inserción de flujo (<<) y extracción (>>) permiten que las clases personalizadas funcionen con std::cout y std::cin. Estos operadores deben implementarse como funciones que no son miembros porque el operando de la izquierda es un objeto de flujo, no su clase.

Sintaxis Básica

class Point {
    int x, y;
    
public:
    Point(int x, int y) : x(x), y(y) {}
    
    // Declare as friend to access private members
    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;
}

Puntos Clave

  • Ambos operadores devuelven una referencia al flujo para permitir el encadenamiento (por ejemplo, std::cout << p1 << p2)
  • El operador de inserción (<<) toma el objeto por referencia const ya que solo lee datos
  • El operador de extracción (>>) toma una referencia no constante porque modifica el objeto
  • Use declaraciones friend para permitir que estas funciones que no son miembros accedan a los miembros privados

Ejemplo de Uso

Point p(3, 4);
std::cout << "Location: " << p << std::endl;    // Output: Location: (3, 4)

Point p2(0, 0);
std::cin >> p2;    // Read two integers into p2

Pruébalo tú mismo

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

int main() {
    // TODO: Crea dos objetos Temperature
    
    // TODO: Usa el operador de extracción (>>) para leer dos temperaturas de std::cin
    
    // TODO: Muestra las temperaturas usando el operador de inserción (<<)
    // Formato:
    // Temperatura 1: <temp1>
    // Temperatura 2: <temp2>
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos