2008-09-22 1335 views
7

¿Hay alguna forma de declarar un objeto de una clase antes de que la clase se cree en C++? Pregunto porque estoy tratando de usar dos clases, la primera necesita tener una instancia de la segunda clase dentro de ella, pero la segunda clase también contiene una instancia de la primera clase. Me doy cuenta de que puede pensar que podría entrar en un ciclo infinito, pero en realidad necesito crear una instancia de la segunda clase antes de la primera clase.Declarar un objeto incluso antes de que se cree esa clase

Respuesta

37

No se puede hacer algo como esto:

class A { 
    B b; 
}; 
class B { 
    A a; 
}; 

El problema más obvio es el compilador no sabe cómo grande que tiene que hacer la clase A, debido a que el tamaño de B depende del tamaño de A!

Puede, sin embargo, hacer esto:

class B; // this is a "forward declaration" 
class A { 
    B *b; 
}; 
class B { 
    A a; 
}; 

La declaración de clase B como una declaración adelantada permite el uso de punteros (y referencias) a esa clase y sin embargo tener toda la definición de clase.

5

No se puede declarar una instancia de una clase no definida pero se puede declarar un puntero a una :

class A; // Declare that we have a class A without defining it yet. 

class B 
{ 
public: 
    A *itemA; 
}; 

class A 
{ 
public: 
    B *itemB; 
}; 
+0

... o una referencia a uno: MyClass & rMyObject; –

0

Está tan cerca de lo que quiere: La primera clase contiene la segunda clase, pero la segunda clase (que se creará primero) solo tiene una referencia a la primera clase?

+0

En realidad estoy tratando de hacer lo contrario, donde la primera clase hace referencia a la segunda clase y la segunda clase contiene una instancia de la primera clase. –

0

Esto se denomina referencia cruzada. Vea here un ejemplo.

2

Hay an elegant solution usando plantillas.

template< int T > class BaseTemplate {}; 
typedef BaseTemplate<0> A; 
typedef BaseTemplate<1> B; 
// A 
template<> class BaseTemplate<0> 
{ 
public: 
    BaseTemplate() {} // A constructor 
    B getB(); 
} 

// B 
template<> class BaseTemplate<1> 
{ 
public: 
    BaseTemplate() {} // B constructor 
    A getA(); 
} 

inline B A::getB() { return A(); } 
inline A B::getA() { return B(); } 

Este código funcionará! Entonces, ¿por qué funciona ? La razón tiene que ver con cómo se compilan las plantillas . Las plantillas retrasan la creación de las firmas de la función hasta que realmente utilice la plantilla en algún lugar. Esto significa que ni getA() ni getB() tendrán sus firmas analizadas hasta que después de ambas clases A y B ya hayan sido completamente declaradas. Esa es la magia de este método.

+0

Interesante (aunque contiene varios errores ortográficos). Pero los 'getA' y 'getB' son en realidad fábricas: devuelven nuevas instancias (por valor). Una instancia de A no tiene una B ni una instancia de B tiene una A. – jwfearn

Cuestiones relacionadas