Menu
Coddy logo textTech

Classes Aninhadas e Internas

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 38 de 104.

Uma classe aninhada é uma classe definida dentro de outra classe. Esta técnica ajuda a organizar o código agrupando tipos relacionados e pode melhorar o encapsulamento ao ocultar detalhes de implementação.

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

A classe aninhada Node está fortemente acoplada à LinkedList - ela só faz sentido nesse contexto. Ao aninhá-la, sinalizamos esse relacionamento e evitamos poluir o namespace global com um nome genérico como "Node".

Classes aninhadas seguem as mesmas regras de acesso que você aprendeu. Uma classe aninhada declarada na seção private é acessível apenas dentro da classe externa.

Quando declarado como public, o código externo pode usá-lo com o operador de escopo:

LinkedList::Node node(42);    // Apenas se Node for público

Um detalhe importante: a classe aninhada não tem acesso automático aos membros privados da classe externa. Elas são classes separadas que por acaso compartilham um namespace.

Se a classe aninhada precisar de acesso, você deve declará-la como friend, como mostrado no exemplo acima.

challenge icon

Desafio

Fácil

Vamos construir um sistema simples de gerenciamento de tarefas onde as tarefas são organizadas dentro de um projeto. Este é um cenário perfeito para classes aninhadas — uma Task só faz sentido dentro do contexto de um Project, então vamos aninhá-la internamente para manter nosso código organizado e evitar poluir o namespace global.

Você criará dois arquivos para organizar seu código:

  • Project.h: Defina uma classe Project que contenha uma classe Task aninhada.

    Sua classe Task aninhada deve ser declarada na seção public de Project para que possa ser acessada de fora. Ela deve armazenar um nome de tarefa (string) e um status de conclusão (bool). Forneça a ela um construtor que receba o nome e defina a tarefa como incompleta por padrão. Inclua os métodos complete() para marcá-la como concluída, isComplete() para verificar seu status e getName() para recuperar o nome.

    A classe Project em si deve armazenar um nome de projeto (string) e uma coleção de ponteiros para Task. Forneça um construtor que receba o nome do projeto, um método addTask(const std::string& taskName) que cria uma nova tarefa e a adiciona ao projeto, um método completeTask(const std::string& taskName) que encontra e conclui uma tarefa pelo nome, e um método displayStatus() que mostra o nome do projeto seguido pelo status de cada tarefa.

    Como Task está aninhada dentro de Project, a classe Project pode trabalhar com as tarefas diretamente. Não se esqueça de limpar as tarefas alocadas dinamicamente no destruidor.

  • main.cpp: Reúna tudo lendo um nome de projeto e dois nomes de tarefas da entrada (três linhas no total). Crie um Project com o nome fornecido, adicione ambas as tarefas a ele e, em seguida, exiba o status inicial. Conclua a primeira tarefa e exiba o status novamente para mostrar a alteração.

    O formato de saída para displayStatus() deve ser:

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

    Use [complete] ou [incomplete] com base no status de cada tarefa.

Este desafio demonstra como classes aninhadas ajudam a organizar tipos relacionados — a classe Task está fortemente acoplada ao Project e não faria sentido por si só. Ao aninhá-la, sinalizamos esse relacionamento claramente em nossa estrutura de código.

Folha de consulta

Uma classe aninhada é uma classe definida dentro de outra classe. Ela ajuda a organizar o código agrupando tipos relacionados e melhora o encapsulamento.

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

Classes aninhadas seguem as regras de acesso padrão. Uma classe aninhada na seção privada é acessível apenas dentro da classe externa. Quando declarada como pública, o código externo pode usá-la com o operador de escopo:

LinkedList::Node node(42);    // Apenas se Node for pública

A classe aninhada não tem acesso automático aos membros privados da classe externa. Se o acesso for necessário, declare-a como amiga (friend):

friend class LinkedList;

Experimente você mesmo

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

using namespace std;

int main() {
    // Ler entrada
    string projectName;
    string task1Name;
    string task2Name;
    
    getline(cin, projectName);
    getline(cin, task1Name);
    getline(cin, task2Name);
    
    // TODO: Criar um Projeto com o nome fornecido
    
    // TODO: Adicionar ambas as tarefas ao projeto
    
    // TODO: Exibir o status inicial
    
    // TODO: Concluir a primeira tarefa
    
    // TODO: Exibir o status novamente para mostrar a alteração
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos