2009-12-23 11 views
11

que tienen una clase como esta:C++: ¿auto_ptr + forward declaration?

class Inner; 

class Cont 
{ 
public: 
    Cont(); 
    virtual ~Cont(); 
private: 
    Inner* m_inner; 
}; 

en el .cpp, el constructor crea una instancia de Inner con new y el destructor delete es todo. Esto está funcionando bastante bien.
Ahora quiero cambiar este código a utilizar auto_ptr así escribo:

class Inner; 

class Cont 
{ 
public: 
    Cont(); 
    virtual ~Cont(); 
private: 
    std::auto_ptr<Inner> m_inner; 
}; 

Ahora, el constructor inicializa la auto_ptr y el destructor no hace nada.

Pero no funciona. el problema parece surgir cuando estoy instanciando esta clase. Aparece esta advertencia:

advertencia C4150: eliminación del puntero a tipo incompleto 'Inner'; sin destructor llamado

Bueno, esto es, obviamente, muy mal y entiendo por qué sucede, el compilador no sabe nada de la d'tor de Inner cuando una instancia de la plantilla de auto_ptr<Inner>

Así que mi pregunta : ¿Hay alguna manera de usar auto_ptr con una declaración forward como la que hice en la versión que solo usa punteros?
Tener que #include cada clase que declaro un puntero es una gran molestia y, a veces, simplemente imposible. ¿Cómo se maneja este problema generalmente?

+0

Solía ​​obtener este problema cuando declaraba un destructor vacío (o no lo declaraba) en el archivo de encabezado de la clase Cont. A partir de su ejemplo, parece que lo está haciendo correctamente, pero solo quería resaltar este problema. – rui

+0

El d'tor se declara en el cpp, y aparece la advertencia de la creación del 'auto_ptr' dentro de la clase. – shoosh

Respuesta

12

Debe incluir el encabezado que define class Inner en el archivo donde se encuentra la implementación Cont::~Cont(). De esta forma, todavía tiene una declaración directa en el encabezado que define class Cont y el compilador ve la definición class Inner y puede llamar al destructor.

//Cont.h 
class Inner; // is defined in Inner.h 
class Cont 
{ 
    virtual ~Cont(); 
    std::auto_ptr<Inner> m_inner; 
}; 

// Cont.cpp 
#include <Cont.h> 
#include <Inner.h> 

Cont::~Cont() 
{ 
} 
+0

Lo hago, pero la advertencia indica que 'Inner' necesita definirse en la línea de la instanciación' auto_ptr', dentro de la clase. – shoosh

+1

Eso es muy extraño. ¿Es eso Visual C++? – sharptooth

+0

sí lo es, MSVC2008 – shoosh

3

En su lugar, puede considerar boost :: shared_ptr(). No tiene desventajas prácticas en lugar de rendimiento, y es mucho más amigable para reenviar declaraciones:

boost::shared_ptr<class NeverHeardNameBefore> ptr;

está bien, sin declaraciones adicionales por encima.

shared_ptr hace más que auto_ptr, como el recuento de referencias, pero no debería dañar si no lo necesita.

+0

O 'boost :: scoped_ptr' que está más cerca, excepto que ni siquiera intenta pretender que sus instancias se puedan copiar. Pero aún no responde a la pregunta de cómo se debe utilizar con tipos incompletos (creo que tendrá que definir un destructor para cuando el tipo esté completo). – UncleBens

0

This question (eliminación de objeto con destructor privado) y this question (cómo escribir la plantilla completa) pueden serle de ayuda.

+0

no, en realidad no. – shoosh

0

No se supone técnicamente que cree instancias de plantillas de biblioteca estándar con tipos incompletos, aunque no conozco ninguna implementación en la que esto no funcione. En la práctica, la respuesta de Sharptooth es lo que también recomendaría.

Realmente no había nada de malo con el uso de un puntero desnudo para su puntero impl, siempre que llame a eliminar en su destructor. Probablemente también deba implementar o deshabilitar el constructor de copias y el operador de asignación.

4

Resulta que el problema se produce solo cuando hago el c'tor en línea.Si pongo el c'tor en el cpp, después de la declinación de Inner todo está bien.

1

La declaración directa en el encabezado está bien si implementa el destructor en el archivo cont.cpp e incluye inner.h, como otros señalaron.

El problema podría estar en el uso de Cont. En cada cpp que usa (y destruye) Cont, debe incluir cont.h AND inner.h. Eso resolvió el problema en mi caso.

3

Parece ridículo pero resolví el mismo problema agregando #include <memory> al archivo Cont.h.