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 deletesentar. 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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top