Domanda

Ho una classe come questa:

class Inner;

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

nel cpp, il costruttore crea un'istanza di Inner con new e il distruttore deletes IT. Questo sta funzionando abbastanza bene.
Ora voglio cambiare questo codice per utilizzare auto_ptr così scrivo:

class Inner;

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

Ora, il costruttore inizializzato il auto_ptr e il distruttore non fa nulla.

Ma non funziona. il problema sembra sorgere quando sto un'istanza di questa classe. Ottengo questo avvertimento:

  

C4150 di avviso: la cancellazione del puntatore   tipo incompleto 'interno'; no   distruttore chiamato

Bene, questo è ovviamente molto male e capisco perché accade, il compilatore non conosce il d'tor di Inner quando si crea un'istanza del modello di auto_ptr<Inner>

Quindi la mia domanda: C'è un modo per utilizzare auto_ptr con una dichiarazione anticipata come ho fatto nella versione che utilizza i puntatori solo semplici
? Dovendo #include ogni classe dichiaro un puntatore a è un enorme fastidio e, a volte, semplicemente impossibile. Come è questo problema di solito gestito?

È stato utile?

Soluzione

È necessario includere l'intestazione che definisce class Inner nel file in cui si trova l'attuazione Cont::~Cont(). In questo modo si ha ancora una dichiarazione anticipata di teh intestazione definizione class Cont e il compilatore vede definizione class Inner e può chiamare il distruttore.

//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()
{
}

Altri suggerimenti

Si scopre che il problema si verifica solo quando faccio la linea c'tor. Se metto il c'tor nel cpp, dopo la decleration di Inner del tutto ok.

Si può considerare boost :: shared_ptr () invece. Non ha svantaggi pratici, invece di prestazioni, ed è molto più amichevole per inoltrare dichiarazioni:

boost::shared_ptr<class NeverHeardNameBefore> ptr;

va bene, senza dichiarazioni aggiuntivi di cui sopra.

shared_ptr fa più di auto_ptr, come ad esempio il conteggio di riferimento, ma non dovrebbe nuocere se non ne hai bisogno.

Sembra essere ridicolo, ma ho risolto lo stesso problema aggiungendo #include <memory> al file Cont.h.

La dichiarazione anticipata nell'intestazione è ok se si implementa il distruttore nel file cont.cpp e si include inner.h, come altri hanno sottolineato.

Il problema potrebbe essere l'uso di Cont. In ogni cpp che utilizza (e distrugge) Cont è necessario includere cont.h E inner.h. Che ha risolto il problema nel mio caso.

Questa domanda (cancellando oggetto con distruttore privato) e this domanda (come scrivere template isComplete) possono essere aiutare.

Non si suppone tecnicamente per istanziare i modelli della libreria standard con tipi incompleti, anche se so di alcuna implementazione in cui questo non funzionerà. In pratica, la risposta di Sharptooth è quello che io consiglierei anche.

In realtà non c'era niente di sbagliato con l'utilizzo di un puntatore nudo per il puntatore impl, a patto che si chiama cancellare su di esso nel vostro distruttore. Probabilmente si dovrebbe anche implementare o disabilitare il costruttore di copia e l'assegnazione dell'operatore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top