¿Cómo crear dos clases en C ++ que se usen como datos?

Estoy buscando crear dos clases, cada una de las cuales contiene un objeto del otro tipo de clase. ¿Cómo puedo hacer esto? Si no puedo hacer esto, ¿hay algún problema, como que cada clase contenga un puntero al otro tipo de clase? ¡Gracias!

Esto es lo que tengo:

Archivo: bar.h

#ifndef BAR_H #define BAR_H #include "foo.h" class bar { public: foo getFoo(); protected: foo f; }; #endif 

Archivo: foo.h

 #ifndef FOO_H #define FOO_H #include "bar.h" class foo { public: bar getBar(); protected: bar b; }; #endif 

Archivo: main.cpp

 #include "foo.h" #include "bar.h" int main (int argc, char **argv) { foo myFoo; bar myBar; } 

$ g ++ main.cpp

 In file included from foo.h:3, from main.cpp:1: bar.h:6: error: 'foo' does not name a type bar.h:8: error: 'foo' does not name a type 

No puede tener dos clases que contengan objetos del otro tipo, ya que de lo contrario necesitaría un espacio infinito para el objeto (ya que foo tiene una barra que tiene un foo que tiene una barra, etc.)

Sin embargo, puede hacer esto haciendo que las dos clases almacenen punteros entre sí. Para hacer esto, necesitarás usar declaraciones directas para que las dos clases conozcan la existencia de la otra:

 #ifndef BAR_H #define BAR_H class foo; // Say foo exists without defining it. class bar { public: foo* getFoo(); protected: foo* f; }; #endif 

y

 #ifndef FOO_H #define FOO_H class bar; // Say bar exists without defining it. class foo { public: bar* getBar(); protected: bar* f; }; #endif 

Tenga en cuenta que los dos encabezados no se incluyen entre sí. En cambio, solo saben de la existencia de la otra clase a través de las declaraciones directas. Luego, en los archivos .cpp para estas dos clases, puede #include el otro encabezado para obtener la información completa sobre la clase. Estas declaraciones avanzadas le permiten romper el ciclo de referencia de “foo needs bar needs foo needs bar”.

Eso no tiene sentido. Si A contiene B y B contiene A, sería un tamaño infinito. Imagina poner dos cajas y tratar de poner ambas cosas en el otro. No funciona, ¿verdad?

Sin embargo, los punteros funcionan:

 #ifndef FOO_H #define FOO_H // Forward declaration so the compiler knows what bar is class bar; class foo { public: bar *getBar(); protected: bar *b; }; #endif 

Correcto, solo para agregar,

los métodos anteriores solo le permitirán tener punteros a dichas clases.

En mis viajes, he encontrado que también se puede hacer una función que crea una instancia de una clase que tiene un puntero (imagen de código, código real al final) :

código y ejecución

Aquí incluye el encabezado de la clase que está “generando”, para que el comstackdor tenga información real sobre él y pueda crearlo.

Por supuesto, esto también le permite tener una instancia de B dentro de A (imagen de código, código real al final) :

b dentro de un kappa

Probablemente también puedas pensar en alguna otra cosa kewl, gn.


Código sin imagen

Ejemplo 1

ah :

 #pragma once #include "bh" struct A { char aye, beye, ceye; B createB(unsigned val); }; 

a.cpp :

 #include "ah" BA::createB(unsigned val){ return {69, this}; } 

bh :

 #pragma once struct A; struct B { unsigned ellel; A* dad; B& printOurEllel(); }; 

b.cpp :

 #include  #include "bh" B& B::printOurEllel(){ printf("ellel: %d\n", this->ellel); return *this; } 

principal :

 #include  #include "ah" #include "bh" int main() { A elgay = { 1, 2, 3 }; printf("%d\n", elgay.createB(69).printOurEllel().dad->beye); getchar(); } 

resultado :

 ellel: 69 2 

Ejemplo 2

ah :

 #pragma once #include "bh" struct A { char aye, beye, ceye; B yeetos; }; 

bh :

 #pragma once struct A; struct B { unsigned ellel; A* dad; B& printOurEllel(); }; 

b.cpp :

 #include  #include "bh" B& B::printOurEllel(){ printf("ellel: %d\n", this->ellel); return *this; } 

principal :

 #include  #include "ah" #include "bh" int main() { A elgay = { 1, 2, 3, {69, &elgay} }; printf("%d\n", elgay.yeetos.printOurEllel().dad->beye); getchar(); } 

resultado :

 ellel: 69 2