Estructura general
La clase base define la interfaz común con dos operandos y un método virtual para calcular el resultado. Cada subclase implementa su propia lógica de cálculo. La fábrica utiliza un identificador de operación para devolver la instancia correspondiente.
Implementación
#pragma once
#include <iostream>
#include <stdexcept>
// Clase base abstracta para operaciones aritméticas
class CCalculo {
protected:
double valorX;
double valorY;
public:
CCalculo() : valorX(0.0), valorY(0.0) {}
void asignarX(double x) { valorX = x; }
void asignarY(double y) { valorY = y; }
double obtenerX() const { return valorX; }
double obtenerY() const { return valorY; }
virtual double calcular() { return 0.0; }
virtual ~CCalculo() = default;
};
// Subclase: Suma
class CSuma : public CCalculo {
public:
double calcular() override {
return obtenerX() + obtenerY();
}
};
// Subclase: Resta
class CResta : public CCalculo {
public:
double calcular() override {
return obtenerX() - obtenerY();
}
};
// Subclase: Multiplicación
class CMultiplicacion : public CCalculo {
public:
double calcular() override {
return obtenerX() * obtenerY();
}
};
// Subclase: División
class CDivision : public CCalculo {
public:
double calcular() override {
if (obtenerY() == 0.0) {
throw std::runtime_error("El divisor no puede ser cero.");
}
return obtenerX() / obtenerY();
}
};
// Fábrica de operaciones
class CFabricaOperaciones {
public:
static CCalculo* construir(char operador) {
switch (operador) {
case '+': return new CSuma();
case '-': return new CResta();
case '*': return new CMultiplicacion();
case '/': return new CDivision();
default:
throw std::runtime_error("Operador no reconocido.");
}
}
};
Programa principal
#include "Operacion.h"
#include <iostream>
#include <memory>
int main() {
double a, b;
char op;
std::cout << "Ingrese la operacion (ej: 5 + 3): ";
std::cin >> a >> op >> b;
try {
std::unique_ptr<CCalculo> calculo(CFabricaOperaciones::construir(op));
calculo->asignarX(a);
calculo->asignarY(b);
std::cout << "Resultado: " << calculo->calcular() << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
En esta implementación se han introducido varias mejoras respecto al diseño básico: el uso de std::unique_ptr garantiza la liberación automática de memoria, el manejo de errores se realiza mediante excepciones en lugar de llamadas directas al sistema, y el destructor virtual por defecto en la clase base asegura una dsetrucción correcta de las subclases.