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 p2Desafío
FácilVamos 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 claseTemperatureque almacene un valor en Celsius (como undouble) y una etiqueta de unidad (como unchar, 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()ygetUnit()(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 Co77.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 formatovalue unit(por ejemplo,25.5 C).Crea dos objetos
Temperatureutilizando el operador de extracción para leerlos destd::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 FLa 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 referenciaconstya que solo lee datos - El operador de extracción (
>>) toma una referencia no constante porque modifica el objeto - Use declaraciones
friendpara 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 p2Prué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;
}
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
1Fundamentos de OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genérico