2014-12-06 13 views
10

dire che ho due classi:Unique_ptr e dichiarazione anticipata

"foo.h"

#pragma once  
class Foo 
{ 
public: 
    Foo() 
    { 

    }; 

    ~Foo() 
    { 

    }; 
}; 

"A.h"

#pragma once 
#include <memory> 

class Foo; 

class A 
{ 
public: 
    A(){}; 
    ~A(){}; 

    std::unique_ptr<Foo> foo; 
}; 

A detiene un unique_ptr di Foo. Non volevo includere Foo in "A.h", quindi l'ho inoltrato. Con solo in avanti dichiarando la classe Foo in "Ah", ottengo un errore di compilazione:

error C2027: use of undefined type 'Foo' 
error C2338: can't delete an incomplete type 

Così stavo seguendo this articolo su come evitare questo errore e si è trasferito distruttore di A in un proprio file cpp in cui ho includere anche Foo:

"A.cpp"

#include "A.h" 

#include "Foo.h" 

A::A() 
{ 

} 

A::~A() 
{ 

} 

Dopo aver implementato il distruttore di a in "A.cpp", sono in grado di compilare il programma, perché la classe Foo è conosciuto in " A.cpp". Questo sembra logico, perché unique_ptr ha bisogno del tipo completo per chiamare il suo distruttore. Ma con mia sorpresa, dopo aver commentato il costruttore di A (in "A.h" e in "A.cpp"), ottengo lo stesso errore. Com'è possibile? Perché il compilatore si lamenta di non essere in grado di chiamare il distruttore di Foo quando A non ha un costruttore?

MODIFICA: Ho caricato i 4 file in modo da poter testare il programma. sto usando MSVC++ di Visual Studio 2013.

http://www.filedropper.com/test_61

+5

'A' ha un costruttore quando si commento la vostra Constructo r: un costruttore predefinito viene fornito dal compilatore e questo costruttore ottiene una definizione in linea. – dyp

+0

Sì, ma con il costruttore standard ottengo l'errore del compilatore che non può eliminare un tipo completo. Quando scrivo il mio costruttore vuoto, che dovrebbe apparire uguale a quello predefinito, non ottengo questi errori del compilatore. – abcheudg234

+0

Mostraci il codice che non funziona? –

risposta

-1

non è possibile per 'A' di non avere un costruttore.

Se si commenta il costruttore che hai scritto, il compilatore creerà per te un costruttore predefinito e non si troverà necessariamente nello stesso posto definito da te. Causando detto problema.

+1

Ma perché devo definire il costruttore in A.cpp? Capisco che il compilatore si lamenta che il distruttore di A deve essere definito da qualche parte dove Foo.h è incluso - in modo che sia un tipo completo e il distruttore di A possa effettivamente distruggere Foo. Ma non capisco perché A's CONstructor debba essere definito anche in A.cpp. Puoi provare il codice copiando le classi e istanziando A in main(). Quando si commenta il costruttore di A, il codice non verrà compilato. – abcheudg234

+3

Che compilatore stai citando? –

+1

Sto usando il compilatore MSVC++ di Visual Studio 2013. – abcheudg234

14

Il costruttore ha bisogno di accedere al deleter esattamente nello stesso modo in cui il distruttore fa: sicurezza rispetto alle eccezioni richiede che il costruttore sia in grado di roll-back inizializzazione di tutti i membri nel caso in cui il corpo del costruttore getta:

[C++14: 12.6.2/10]: In a non-delegating constructor, the destructor for each potentially constructed subobject of class type is potentially invoked (12.4). [ Note: This provision ensures that destructors can be called for fully-constructed sub-objects in case an exception is thrown (15.2). —end note ]

correlati:

Problemi correlati