C ++: Declaração Auto_ptr+Avanço?
-
21-09-2019 - |
Pergunta
Eu tenho uma aula como esta:
class Inner;
class Cont
{
public:
Cont();
virtual ~Cont();
private:
Inner* m_inner;
};
No .CPP, o construtor cria uma instância de Inner
com new
e o destruidor delete
sentar. Isso está funcionando muito bem.
Agora eu quero alterar este código para usar auto_ptr
Então eu escrevo:
class Inner;
class Cont
{
public:
Cont();
virtual ~Cont();
private:
std::auto_ptr<Inner> m_inner;
};
Agora, o construtor inicializou o auto_ptr
E o destruidor não faz nada.
Mas não funciona. O problema parece surgir quando estou instantando essa aula. Eu recebo este aviso:
Aviso C4150: exclusão do ponteiro ao tipo incompleto 'interno'; Nenhum destruidor chamado
Bem, isso é obviamente muito ruim e eu entendo por que acontece, o compilador não sabe sobre o d'or de Inner
Ao instantar o modelo de auto_ptr<Inner>
Então, minha pergunta: existe uma maneira de usar auto_ptr
Com uma declaração avançada, como eu fiz na versão que usa ponteiros simplesmente simples?
Ter de #include
Toda aula que eu declaro um ponteiro é um enorme aborrecimento e, às vezes, simplesmente impossível. Como esse problema geralmente é tratado?
Solução
Você precisa incluir o cabeçalho definindo class Inner
no arquivo onde Cont::~Cont()
implementação está localizada. Dessa forma, você ainda tem uma declaração avançada na definição do cabeçalho class Cont
e o compilador vê class Inner
definição e pode chamar o destruidor.
//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()
{
}
Outras dicas
Acontece que o problema ocorre apenas quando eu faço o C'Tor embutido. Se eu colocar o C'Tor no CPP, após a repartição de Inner
Está tudo bem.
Você pode considerar o boost :: shared_ptr (). Não tem desvantagens práticas em vez de desempenho e é muito mais amigável para encaminhar declarações:
boost::shared_ptr<class NeverHeardNameBefore> ptr;
está bem, sem declarações extras acima.
Shared_Ptr faz mais do que auto_ptr, como contagem de referência, mas não deve prejudicar se você não precisar.
Parece ser ridículo, mas resolvi o mesmo problema adicionando #include <memory>
para o arquivo cont.h.
A declaração avançada no cabeçalho é boa se você implementar o destruidor no arquivo cont.cpp e incluir o Inner.H, como outros apontaram.
O problema pode estar no uso de cont. Em cada CPP que usa (e destrói) cont, você deve incluir cont.h e interno.h. Isso resolveu o problema no meu caso.
Essa questão (Excluindo objeto com destruidor privado) e essa questão (Como escrever um modelo ISComplete) pode ajudá -lo.
Você não deveria tecnicamente instanciar modelos de biblioteca padrão com tipos incompletos, embora eu não conheça nenhuma implementação onde isso não funcionará. Na prática, a resposta de Sharptooth é o que eu recomendaria também.
Realmente não havia nada de errado em usar um ponteiro nu para o seu ponteiro Impl, desde que você chame a exclusão nele em seu destruidor. Você provavelmente também deve implementar ou desativar o construtor de cópias e o operador de atribuição.