2014-01-14 1 views
1

У меня есть очень простая реализация отражения, которая включает класс Type, который создает экземпляр объекта для описываемого класса. Лишенный вплоть до соответствующих частей, то она выглядит следующим образом:Является ли пользовательским удалением для std :: unique_ptr допустимым местом для ручного вызова деструктора?

Type.h:

class Plugin; // forward declaration 

typedef std::unique_ptr<Plugin> PluginPtr; 

namespace Reflection { 

    class Type { 
    public: 
     explicit Type(PluginPtr(*)()); 
     PluginPtr CreateInstance(); 
    private: 
     PluginPtr(*_createInstance_Handler)(); 
    }; 

} 

Type.cpp:

Type::Type(PluginPtr(*createInstance_Handler)()) : 
    _createInstance_Handler(createInstance_Handler) {} 

PluginPtr CreateInstance() { return (*_createInstance_Handler)(); } 

Фактическая логика конкретизации расположен в Plugin классе (и Кроме того, в каждом из его потомков):

Plugin.h:

class Plugin { 
public: 
    virtual ~Plugin(); 
    static const Reflection::Type Type; 
private: 
    static PluginPtr CreateInstance(); 

plugin.cpp

Plugin::~Plugin() {} 

const Reflection::Type Plugin::Type(CreateInstance); 

PluginPtr Plugin::CreateInstance() { return PluginPtr(new Plugin); } 

Когда я пытаюсь скомпилировать это я получаю эти ошибки (в Visual Studio 2013):

error C2027: use of undefined type 'Plugin' 
error C2338: can't delete an incomplete type 
warning C4150: deletion of pointer to incomplete type 'Plugin'; no destructor called 

я выкопал вокруг немного, и по-видимому, это вызвано удалением std :: unique_ptr (находящимся внутри определения класса класса, на котором он работает). Я где-то читал, что если я поставлю свой собственный делеттер, эта проблема исчезнет. Поэтому я пересмотрел PluginPtr к этому:

typedef std::unique_ptr<Plugin, PluginDeleter> PluginPtr 

The (сборник) проблема действительно уходит, но вопрос тогда, может/должен это PluginDeleter вызова ~Plugin() вручную (для того, чтобы плагин (и любой полученный объект плагинPtr может указывать на!) правильно разрушен)? И где/как лучше всего объявить/определить его, чтобы у меня не возникала проблема с неполными типами?

(или есть лучший способ вообще?)

PS. Работая над своим исходным кодом, я понимаю, что в приведенном выше коде есть ошибка. Последняя строка в Type.cpp следует читать

PluginPtr CreateInstance() { return (_createInstance_Handler)(); } 
+0

'использование неопределенного типа 'Плагин'': вы пытались использовать полный тип раньше? т. е. объявить весь класс, прежде чем использовать его unique_ptr? – Geoffroy

+0

@ Geoffroy: да. – d7samurai

+0

Вы используете 'delete' в своем PluginDeleter? – Geoffroy

ответ

2

Deleter из std::unique_ptr должны удалить объект, то есть уничтожить его (как вы можете предположить, что это должно быть), а затем освободить память, используемую при необходимости.

Если ваш пользовательский Deleter использует оператор delete, то вам не придется вручную вызвать деструктор как:

delete является оператором с очень специфическим поведением: Выражение с удалением оператора, сначала вызывает соответствующий деструктор (для типов классов ), а затем вызывает оператор функции delete (т. е. эту функцию ) для освобождения хранилища.

Если вы создаете указатель, используя статически выделенную память или места размещения нового в статически выделенную память или память не будет не бесплатно до выхода из приложения (к примеру), то вы не должны позвонить оператору delete но вы все равно должны уничтожить объект, поэтому вам нужно вызвать деструктор объекта.

+0

Думаю, я получил его сейчас :) – d7samurai

Смежные вопросы