Principios SOLID en C++: teoría y práctica de nivel avanzado

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: SOLID en el contexto de C++

SOLID es el acrónimo de cinco principios fundamentales del diseño orientado a objetos, formulados por Robert Martin. Para C++, como lenguaje con potente tipado estático, herencia múltiple y RAII, estos principios adquieren especial relevancia. A nivel avanzado, comprender SOLID permite crear sistemas flexibles, comprobables y extensibles, evitando antipatrones como la «clase divina» o el acoplamiento rígido.

En este artículo analizaremos cada principio con ejemplos prácticos de código C++ (17/20), centrándonos en los matices de implementación: uso de std::unique_ptr, std::function, CRTP, destructores virtuales y modismos modernos.



1. Single Responsibility Principle (SRP) — principio de responsabilidad única

Formulación: Una clase debe tener solo una razón para cambiar.

En la práctica, esto significa que la clase es responsable de una entidad de negocio o una sola operación. La violación de SRP conduce al «acoplamiento» de responsabilidades, lo que dificulta las pruebas y la modificación.

Ejemplo de violación

class Report {public:    void generate() { /* creación de datos */ }    void saveToFile(const std::string& path) { /* escritura en archivo */ }    void sendEmail(const std::string& to) { /* envío */ }};

Aquí Report es responsable tanto de la generación, como del guardado y del envío — tres razones para cambiar.

Refactorización con SRP

class Report {public:    void generate() { /* creación de datos */ }};

class ReportSaver {public: void save(const Report& report, const std::string& path);};

class EmailSender {public: void send(const Report& report, const std::string& to);};

Ahora cada clase tiene una única responsabilidad. Esto simplifica las pruebas unitarias y la reutilización.



2. Open/Closed Principle (OCP) — principio de abierto/cerrado

Formulación: Las entidades de software deben estar abiertas para la extensión, pero cerradas para la modificación.

En C++, esto a menudo se implementa mediante polimorfismo (funciones virtuales) o mediante plantillas (CRTP). Para nivel avanzado, consideraremos ambas técnicas.

Enfoque polimórfico (funciones virtuales)

class Shape {public:    virtual double area() const = 0;    virtual ~Shape() = default;};

class Circle : public Shape { double r;public: Circle(double r) : r(r) {} double area() const override { return 3.14 * r * r; }};

class Rectangle : public Shape { double w, h;public: Rectangle(double w, double h) : w(w), h(h) {} double area() const override { return w * h; }};

Agregar una nueva figura (por ejemplo, Triangle) no requiere modificar las clases existentes — solo crear un nuevo heredero.

Enfoque con plantillas (CRTP — Curiously Recurring Template Pattern)

template<typename Derived>class ShapeBase {public:    double area() const { return static_cast<const Derived*>(this)->area_impl(); }};

class Circle : public ShapeBase<Circle> { double r;public: Circle(double r) : r(r) {} double area_impl() const { return 3.14 * r * r; }};

CRTP proporciona polimorfismo estático sin la sobrecarga de las llamadas virtuales, lo cual es crítico para C++ de alto rendimiento.



3. Liskov Substitution Principle (LSP) — principio de sustitución de Barbara Liskov

Formulación: Los objetos de una clase base deben poder ser reemplazados por objetos de sus clases derivadas sin alterar la corrección del programa.

La violación clásica de LSP en C++ es la redefinición de un método virtual debilitando las precondiciones o fortaleciendo las postcondiciones. Consideremos un ejemplo con la jerarquía «Rectángulo — Cuadrado».

Antipatrón

class Rectangle {protected:\                

Blogs

Book Recommendations