✅ Objetivo: Dominar las clases abstractas puras, el polimorfismo real, la gestión de recursos y los patrones de diseño como Factory Method. ✅ Nivel: Avanzado ✅ Temas clave: clases abstractas, métodos puros, punteros polimórficos, herencia, gestión de memoria dinámica, Rule of Three
- Clases Abstractas y Métodos Puros
- Interfaces en C++
- Polimorfismo Real: Acceso Dinámico por Punteros
- Factory Pattern
- Regla de tres en Jerarquías
- Ejemplo Completo: Materia RPG
- Errores Comunes
- Buenas Prácticas
📘 ¿Qué es? Una clase abstracta tiene al menos un método virtual puro:
virtual void metodo() const = 0;🎯 No se puede instanciar directamente, solo derivar.
class AMateria {
public:
virtual void usar() const = 0; // método puro
virtual ~AMateria() {}
};🧪 No válido:
AMateria a; // ❌ Error: clase abstracta📘 ¿Qué es?
Una interfaz es una clase que contiene solo métodos virtual ... = 0.
Equivale a interfaces en Java o abstract base classes en Python.
class ICharacter {
public:
virtual std::string const & getName() const = 0;
virtual void equip(AMateria* m) = 0;
virtual void use(int idx, ICharacter& target) = 0;
virtual ~ICharacter() {}
};📘 ¿Por qué es necesario? Para acceder a comportamiento dinámico, necesitas acceder a objetos derivados por puntero o referencia a la base.
AMateria* materia = new Hielo();
materia->usar(); // ejecuta Hielo::usar()🎯 Si usas objetos por valor → object slicing.
📘 ¿Qué es? Un patrón de diseño donde un objeto crea instancias sin saber su tipo exacto.
class IMateriaSource {
public:
virtual void learnMateria(AMateria*) = 0;
virtual AMateria* createMateria(std::string const & type) = 0;
};🧪 Uso:
MateriaSource src;
src.learnMateria(new Cure());
AMateria* m = src.createMateria("cure");🎯 Permite crear objetos a partir de un string → útil para RPG o UI dinámicas.
📘 ¿Qué es?
Si tu clase gestiona recursos dinámicos (como new), debes implementar:
| Método | ¿Para qué sirve? |
|---|---|
| Constructor por copia | Copia profunda del recurso |
| Operador de asignación | Evita fugas en copia-asignación |
| Destructor | Libera memoria al destruir |
class Character : public ICharacter {
private:
AMateria* inventario[4];
public:
Character(const Character& other); // copia profunda
Character& operator=(const Character& other); // evitar fuga
~Character(); // delete[] inventario
};🎯 Objetivo del proyecto: Simular habilidades mágicas como materias en Final Fantasy.
🧩 Componentes:
AMateria(abstracta)Cure,Ice(concretas)ICharacter(interfaz)Character(implementa ICharacter)IMateriaSource(interfaz)MateriaSource(implementa IMateriaSource)
🧠 Diagrama Simplificado:
[AMateria] <------ [Ice]
↑ ↑
| |
[MateriaSource] --> createMateria("ice")
|
[ICharacter]
↑
[Character]
🧪 Ejemplo de uso:
MateriaSource src;
src.learnMateria(new Ice());
ICharacter* me = new Character("me");
AMateria* tmp = src.createMateria("ice");
me->equip(tmp);
me->use(0, *me); // me usa "ice" sobre sí mismo❌ Instanciar clase abstracta directamente
❌ Object slicing: usar objetos por valor
❌ No implementar destructor virtual → memory leaks
❌ Copiar punteros sin copiar los objetos que apuntan (shallow copy)
❌ No inicializar inventario[] correctamente
✅ Siempre usa punteros para polimorfismo
✅ Usa virtual ~Base() incluso en interfaces
✅ Aplica Rule of Three en clases con punteros
✅ Protege miembros (private) y expón comportamiento (public)
✅ Marca funciones sobrescritas con override
Este proyecto está bajo la licencia MIT. ⚖️📄🆓