Clases anidadas en C++

Jinku Hu 12 octubre 2023
Clases anidadas en C++

Este artículo explicará cómo funcionan las clases y estructuras anidadas en C++.

Definir un objeto class o struct dentro de otra clase en C++

A veces, nuestras clases necesitan los llamados tipos de datos auxiliares, generalmente definidos como objetos struct o class personalizados. Estas clases auxiliares se pueden definir dentro de las otras clases y, en tales casos, se denominarán tipos anidados o clases anidadas. Este último concepto proporciona muchas ventajas para el programador, como buenos límites de alcance y control de acceso.

El siguiente ejemplo se muestra para demostrar un escenario simple en el que podríamos definir una clase anidada. La clase principal - CircularList implementa una lista enlazada circular, y necesita definir un nodo que es un tipo compuesto, llamado - ListNode. En este caso, este último se define en el ámbito global utilizando la palabra clave struct. Por lo tanto, sus miembros son accesibles públicamente por otras clases.

#include <iostream>
#include <string>

using std::string;

struct ListNode {
  struct ListNode *next = nullptr;
  string data;
} typedef ListNode;

class CircularList {
 public:
  explicit CircularList(string data) {
    head = new ListNode;
    head->next = head;
    head->data = std::move(data);
    end = head;
  };

  ListNode *insertNodeEnd(string data);
  ListNode *insertNodeHead(string data);
  void printNodes();

  ~CircularList();

 private:
  ListNode *head = nullptr;
  ListNode *end = nullptr;
};

int main() { return EXIT_SUCCESS; }

Alternativamente, podemos mover la definición de ListNode a la clase CircularList. No se puede acceder a ListNode en el espacio de nombres global, por lo que debemos incluir el espacio de nombres CircularList antes de los nombres de las clases anidadas. Además, es importante qué especificador de acceso tiene la clase anidada, ya que las reglas de control de acceso habituales también se aplican a ellos.

En este caso, ListNode se define como una clase miembro pública y, en consecuencia, se puede acceder desde la función main utilizando la notación CircularList::ListNode. Si una clase anidada se define como un miembro protegido, se puede acceder a ella adjuntando la clase, las clases amigas de esta última y las clases derivadas. Por otro lado, un especificador private para una clase anidada significaría que solo es accesible dentro de la clase adjunta y las clases de amigos.

#include <iostream>
#include <string>

using std::string;

class CircularList {
 public:
  // Helper Types ->
  struct ListNode {
    struct ListNode *next = nullptr;
    string data;
  } typedef ListNode;

  // Member Functions ->
  explicit CircularList(string data) {
    head = new ListNode;
    head->next = head;
    head->data = std::move(data);
    end = head;
  };

  ListNode *insertNodeEnd(string data);
  ListNode *insertNodeHead(string data);
  void printNodes();

  ~CircularList();

 private:
  ListNode *head = nullptr;
  ListNode *end = nullptr;
};

int main() {
  //    ListNode *n1; // Error
  CircularList::ListNode *n2;

  return EXIT_SUCCESS;
}

Por lo general, una clase anidada puede tener especificadores de acceso habituales para sus miembros, y las reglas se aplicarán a la clase adjunta de forma regular. Mientras tanto, una clase anidada no tiene acceso especial a los miembros de la clase adjunta.

Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artículo relacionado - C++ Class