Вопрос

У меня есть такой класс:

class Inner;

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

в .cpp конструктор создает экземпляр Inner с new и деструктор deleteсидеть.Это работает довольно хорошо.
Теперь я хочу изменить этот код, чтобы использовать auto_ptr поэтому я пишу:

class Inner;

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

Теперь конструктор инициализировал auto_ptr и деструктор ничего не делает.

Но это не работает.проблема, похоже, возникает, когда я создаю экземпляр этого класса.Я получаю это предупреждение:

предупреждение C4150:Удаление указателя на неполный тип «внутренний»;Ни один деструктор не называется

Ну это явно очень плохо и я понимаю почему так происходит. Составитель не знает о д'торе Inner при создании экземпляра шаблона auto_ptr<Inner>

Итак, мой вопрос:Есть ли способ использовать auto_ptr с предварительным объявлением, как я сделал в версии, в которой используются только простые указатели?
Того, чтобы #include каждый класс, на который я объявляю указатель, представляет собой огромную проблему, а иногда и просто невозможную.Как обычно решается эта проблема?

Это было полезно?

Решение

Вам необходимо включить заголовок, определяющий class Inner в файл, где Cont::~Cont() находится реализация.Таким образом, у вас все еще есть предварительное объявление в заголовке, определяющем class Cont и компилятор видит class Inner определение и может вызвать деструктор.

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

Другие советы

Оказывается, проблема возникает только тогда, когда я делаю c'tor встроенным.Если я поставлю c'tor в cpp, после объявления Inner все хорошо.

Вместо этого вы можете рассмотреть boost::shared_ptr().Он не имеет практических недостатков, а не производительности, и гораздо удобнее пересылать объявления:

boost::shared_ptr<class NeverHeardNameBefore> ptr;

все в порядке, без дополнительных объявлений выше.

Shared_ptr делает больше, чем auto_ptr, например, подсчитывает ссылки, но это не должно навредить, если вам это не нужно.

Это кажется смешным, но я решил ту же проблему, добавив #include <memory> в файл Cont.h.

Предварительное объявление в заголовке допустимо, если вы реализуете деструктор в файле cont.cpp и включаете внутренний.h, как указывали другие.

Проблема может быть в использовании Cont.В каждый cpp, который использует (и уничтожает) Cont, вы должны включить cont.h И внутренний.h.Это решило проблему в моем случае.

Этот вопрос (удаление объекта с помощью частного деструктора) и этот вопрос (как написать шаблон iscomplete) может вам помочь.

Технически не предполагается создавать экземпляры шаблонов стандартной библиотеки с неполными типами, хотя я не знаю ни одной реализации, в которой это не работало бы.На практике я бы также порекомендовал ответ Sharptooth.

На самом деле нет ничего плохого в использовании голого указателя в качестве указателя реализации, если вы вызываете delete для него в своем деструкторе.Вероятно, вам также следует реализовать или отключить конструктор копирования и оператор присваивания.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top