C ++: auto_ptr + прямое объявление? - PullRequest
12 голосов
/ 23 декабря 2009

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

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 каждого класса, на который я объявляю указатель, является большой проблемой, а порой просто невозможным. Как обычно решается эта проблема?

Ответы [ 7 ]

13 голосов
/ 23 декабря 2009

Вам необходимо включить заголовок, определяющий 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()
{
}
4 голосов
/ 06 июня 2011

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

3 голосов
/ 05 декабря 2012

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

3 голосов
/ 23 декабря 2009

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

boost::shared_ptr<class NeverHeardNameBefore> ptr;

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

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

2 голосов
/ 15 июня 2011

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

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

0 голосов
/ 24 декабря 2009

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

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

0 голосов
/ 23 декабря 2009

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

...