У меня есть класс как это:
class Inner;
class Cont
{
public:
Cont();
virtual ~Cont();
private:
Inner* m_inner;
};
в .cpp конструктор создает экземпляр Inner
с new
и деструктор delete
s это. Это работает вполне прилично.
Теперь я хочу изменить этот код для использования auto_ptr
таким образом, я пишу:
class Inner;
class Cont
{
public:
Cont();
virtual ~Cont();
private:
std::auto_ptr<Inner> m_inner;
};
Теперь, конструктор, инициализированный auto_ptr
и деструктор ничего не делает.
Но это не работает. проблема, кажется, возникает, когда я инстанцирую этого класса. Я получаю это предупреждение:
предупреждение C4150: удаление указателя на неполный 'Внутренний' тип; никакой деструктор не называют
Ну, это очевидно очень плохо, и я понимаю, почему это происходит, компилятор не знает о d'tor Inner
при инстанцировании шаблона auto_ptr<Inner>
Так мой вопрос: Есть ли способ использовать auto_ptr
с предописанием как я сделал в версии, которая использует просто указатели?
Необходимость к #include
каждый класс, на который я объявляю указатель, является огромной стычкой и время от времени, просто невозможный. Как эта проблема обычно решается?
Вам необходимо включить заголовок, определяющий класс Inner
, в файл, где Находится реализация Cont :: ~ Cont ()
. Таким образом, у вас все еще есть предварительное объявление в заголовке, определяющем class Cont
, и компилятор видит определение внутреннего класса
и может вызвать деструктор.
//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()
{
}
Этот вопрос (удаление объекта с помощью частного деструктора) и этот вопрос (как написать iscomplete шаблон) могут вам помочь.
Вместо этого вы можете использовать boost :: shared_ptr (). У него нет практических недостатков вместо производительности, и он гораздо более удобен для пересылки объявлений:
boost :: shared_ptr
в порядке, без дополнительных объявлений выше.
shared_ptr делает больше, чем auto_ptr , например подсчет ссылок, но это не должно повредить, если вам это не нужно.
Технически вы не должны создавать экземпляры стандартных библиотечных шаблонов с неполными типами, хотя я не знаю ни одной реализации, где это не сработает. На практике я бы порекомендовал и Sharptooth.
На самом деле нет ничего плохого в использовании открытого указателя для указателя на impl, если вы вызываете для него delete в своем деструкторе. Вероятно, вам также следует реализовать или отключить конструктор копирования и оператор присваивания.