Menu
Coddy logo textTech

Clases anidadas e internas

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

Una clase anidada es una clase definida dentro de otra clase. Esta técnica ayuda a organizar el código agrupando tipos relacionados y puede mejorar el encapsulamiento al ocultar los detalles de implementación.

class LinkedList {
public:
    class Node {    // Clase anidada
        int data;
        Node* next;
    public:
        Node(int d) : data(d), next(nullptr) {}
        friend class LinkedList;
    };
    
private:
    Node* head;
    
public:
    LinkedList() : head(nullptr) {}
};

La clase anidada Node está estrechamente acoplada a LinkedList - solo tiene sentido en ese contexto. Al anidarla, señalamos esta relación y evitamos contaminar el espacio de nombres global con un nombre genérico como "Node".

Las clases anidadas siguen las mismas reglas de acceso que has aprendido. Una clase anidada declarada en la sección private solo es accesible dentro de la clase externa.

Cuando se declara como público, el código externo puede usarlo con el operador de ámbito:

LinkedList::Node node(42);    // Solo si Node es público

Un detalle importante: la clase anidada no tiene acceso automáticamente a los miembros privados de la clase externa. Son clases separadas que simplemente comparten un espacio de nombres.

Si la clase anidada necesita acceso, debes declararla como friend, como se muestra en el ejemplo anterior.

challenge icon

Desafío

Fácil

Vamos a construir un sistema simple de gestión de tareas donde las tareas se organizan dentro de un proyecto. Este es un escenario perfecto para las clases anidadas: una Task solo tiene sentido dentro del contexto de un Project, por lo que la anidaremos dentro para mantener nuestro código organizado y evitar contaminar el espacio de nombres global.

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

  • Project.h: Define una clase Project que contenga una clase Task anidada.

    Tu clase Task anidada debe declararse en la sección public de Project para que se pueda acceder a ella desde el exterior. Debe almacenar un nombre de tarea (string) y un estado de finalización (bool). Dale un constructor que reciba el nombre y establezca la tarea como incompleta por defecto. Incluye los métodos complete() para marcarla como terminada, isComplete() para verificar su estado y getName() para recuperar el nombre.

    La clase Project en sí debe almacenar un nombre de proyecto (string) y una colección de punteros a Task. Proporciona un constructor que reciba el nombre del proyecto, un método addTask(const std::string& taskName) que cree una nueva tarea y la añada al proyecto, un método completeTask(const std::string& taskName) que busque y complete una tarea por su nombre, y un método displayStatus() que muestre el nombre del proyecto seguido del estado de cada tarea.

    Dado que Task está anidada dentro de Project, la clase Project puede trabajar con las tareas directamente. No olvides limpiar las tareas asignadas dinámicamente en el destructor.

  • main.cpp: Une todo leyendo un nombre de proyecto y dos nombres de tareas de la entrada (tres líneas en total). Crea un Project con el nombre dado, añádele ambas tareas y luego muestra el estado inicial. Completa la primera tarea y muestra el estado de nuevo para mostrar el cambio.

    El formato de salida para displayStatus() debe ser:

    Project: <project_name>
      - <task_name>: [incomplete]
      - <task_name>: [complete]

    Usa [complete] o [incomplete] basándote en el estado de cada tarea.

Este desafío demuestra cómo las clases anidadas ayudan a organizar tipos relacionados: la clase Task está estrechamente ligada a Project y no tendría sentido por sí sola. Al anidarla, señalamos esta relación claramente en nuestra estructura de código.

Hoja de referencia

Una clase anidada es una clase definida dentro de otra clase. Ayuda a organizar el código agrupando tipos relacionados y mejora el encapsulamiento.

class LinkedList {
public:
    class Node {    // Clase anidada
        int data;
        Node* next;
    public:
        Node(int d) : data(d), next(nullptr) {}
        friend class LinkedList;
    };
    
private:
    Node* head;
    
public:
    LinkedList() : head(nullptr) {}
};

Las clases anidadas siguen las reglas de acceso estándar. Una clase anidada en la sección privada solo es accesible dentro de la clase externa. Cuando se declara pública, el código externo puede usarla con el operador de ámbito:

LinkedList::Node node(42);    // Solo si Node es pública

La clase anidada no tiene acceso automáticamente a los miembros privados de la clase externa. Si se necesita acceso, declárela como amiga (friend):

friend class LinkedList;

Pruébalo tú mismo

#include <iostream>
#include <string>
#include "Project.h"

using namespace std;

int main() {
    // Leer la entrada
    string projectName;
    string task1Name;
    string task2Name;
    
    getline(cin, projectName);
    getline(cin, task1Name);
    getline(cin, task2Name);
    
    // TODO: Crear un Project con el nombre dado
    
    // TODO: Añadir ambas tareas al proyecto
    
    // TODO: Mostrar el estado inicial
    
    // TODO: Completar la primera tarea
    
    // TODO: Mostrar el estado de nuevo para ver el cambio
    
    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