C ++: auto_ptr + déclaration anticipée?
-
21-09-2019 - |
Question
J'ai une classe comme ceci:
class Inner;
class Cont
{
public:
Cont();
virtual ~Cont();
private:
Inner* m_inner;
};
dans le Cpp, le constructeur crée une instance de Inner
avec new
et les destructor delete
s il. Cela fonctionne assez bien.
Maintenant, je veux changer ce code pour utiliser auto_ptr
donc j'écris:
class Inner;
class Cont
{
public:
Cont();
virtual ~Cont();
private:
std::auto_ptr<Inner> m_inner;
};
Maintenant, le constructeur a initialisé le auto_ptr
et l'destructor ne fait rien.
Mais cela ne fonctionne pas. le problème semble se poser quand j'instancier cette classe. Je reçois cet avertissement:
C4150 d'avertissement: suppression du pointeur type incomplet « intérieure »; non destructor appelé
Eh bien, ce qui est évidemment très mauvais et je comprends pourquoi il arrive, le compilateur ne connaît pas le d'tor de Inner
lors de l'instanciation du modèle de auto_ptr<Inner>
Ma question: Y at-il un moyen d'utiliser auto_ptr
une déclaration en avant comme je l'ai fait dans la version qui utilise des pointeurs tout simplement
?
Ayant à #include
chaque classe, je déclare un pointeur est un énorme problème et parfois, tout simplement impossible. Comment est-ce problème généralement géré?
La solution
Vous devez inclure l'en-tête définissant class Inner
dans le fichier où la mise en œuvre de Cont::~Cont()
est situé. De cette façon, vous avez encore une déclaration avant dans Teh tête définissant class Cont
et le compilateur voit définition class Inner
et peut appeler le 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()
{
}
Autres conseils
Il s'avère que le problème ne se produit que lorsque je fais la ligne de c'tor. Si je mets le c'tor dans le cpp, après la decleration de tout Inner
va bien.
Vous pouvez envisager de boost :: shared_ptr () à la place. Il n'a pas d'inconvénients pratiques au lieu de la performance, et est beaucoup plus facile de transmettre des déclarations:
boost::shared_ptr<class NeverHeardNameBefore> ptr;
est correct, sans déclarations supplémentaires ci-dessus.
shared_ptr fait plus que auto_ptr, comme le comptage de référence, mais il ne doit pas faire du mal si vous ne avez pas besoin.
Il semble ridicule mais je résolu le même problème en ajoutant #include <memory>
au fichier Cont.h.
La déclaration en avant dans l'en-tête est ok si vous implémentez le destructor dans le fichier cont.cpp et que vous incluez inner.h, comme d'autres ont souligné.
Le problème pourrait être l'utilisation de Cont. Dans chaque cpp qui utilise (et détruit) Cont vous devez inclure cont.h ET inner.h. Cela a résolu le problème dans mon cas.
Cette question (objet suppression avec destructor privé) et this question (comment écrire modèle IsComplete) peut vous aider.
Vous n'êtes pas techniquement censé instancier des modèles de bibliothèque standard avec des types incomplets, bien que je ne connais pas la mise en œuvre où cela ne fonctionnera pas. Dans la pratique, la réponse de Sharptooth est ce que je vous recommande également.
Il n'y avait vraiment rien de mal à l'aide d'un pointeur nu pour votre pointeur impl, aussi longtemps que vous appelez supprimer sur dans votre destructor. Vous devez implémenter probablement ou désactiver le constructeur de copie et d'affectation.