2010-06-15 3 views
1

Вот моя проблема. Я делаю C++ dll, который широко использует экспорт объектов экземпляра. Итак, я возвращаю свои фактические экземпляры в качестве указателей для интерфейса через какой-либо экспортированный заводский метод.Чистый виртуальный деструктор в интерфейсе

Интерфейсы, которые я использую, являются чисто виртуальными, чтобы избежать связывания пробления. Так что мне нужен чистый виртуальный деструктор тоже, и я реализовал один (с пустым телом, как я его разобрал). Все компилируется отлично, за исключением ... Я не вижу, если вызываются фактические деструкторы или нет, потому что когда я добавил

std::cout << "hello destructor";
, я никогда не увижу его.

У меня есть явное «удаление obj» (EDIT: и он вызван из метода «FreeObject» внутри dll), это не проблема.

Я что-то не хватает? Есть ли другой способ удалить мой объект через интерфейс?

EDIT: Опять же, у меня нет несоответствия в управлении памятью, это все внутри dll. Но правый деструктор просто не начинается.

ответ

4

Вы не должны смешивать и сопоставлять вызовы с new и delete через границы DLL.

Вместо этого я рекомендую проверенный метод, который использует COM: AddRef и Release. Когда счетчик ссылок достигает нуля, Release вызывает delete this; изнутри библиотеки DLL, гарантируя соответствие new и delete.

+0

Уже позаботился об этом. Я отредактировал мой вопрос, чтобы быть ясным. – ALOR

+1

Я по-прежнему рекомендую использовать шаблон COM AddRef/Release. 'FreeObject' звучит как ужасно общее имя, как определяется параметр? Убранный указатель должен иметь тип времени компиляции, по крайней мере такой же конкретный, как базовый класс, который объявляет виртуальный деструктор для того, чтобы произошло виртуальное удаление - 'delete (void *) p' никогда не вызовет любого деструктора на' p' , –

+1

Использование нового/удаления через dll bun dries было проблемой 10 лет назад, когда среда исполнения была доступна только как статическая библиотека. Эта проблема была решена с введением общей версии lib для dll runtime (что означает, что для всего приложения имеется одна куча). Если вы не «вручную» загружаете/выгружаете dll, использование нового/удаления через dll bun dries больше не является проблемой. –

0

Вам вообще не нужен деструктор в интерфейсе. Правильный деструктор должен просматриваться только вызывающим абонентом delete. Вне DLL используйте указатель интерфейса как дескриптор, а не то, что вы можете создать/уничтожить. Построение/уничтожение объекта должно быть внутри библиотеки DLL. Вы можете использовать подсчет ссылок или любую другую технику, которую вы хотите, просто предоставляете надлежащий экспорт для доступа к объектам и управления ими, вы определяете, как будет интегрировано управление памятью.

1

Это, как я решил вашу конкретную проблему для динамически загружаемых классов C++ -

Есть базовый класс для всех подключаемых объектов, т.е.

class object_t { 

public: 
    virtual ~object_t(); 

//other type utils... 

}; 

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

class object_t; 

class interface_t { 

public: 
    virtual object_t* object() = 0; 

} 

Объект object_t будет иметь связь, определите его в своей собственной DLL, которую вы свяжете с классами плагинов. Другими полезными крючками для объекта object_t являются копирование, нереста, RTTI и другие типы utils, у моего базового объекта есть spawn(), copy(), object_name(), например.

Таким образом, все конкретные классы производятся от object_t и их соответствующего типа виртуального интерфейса, а все опубликованные (подключаемые) интерфейсы выводятся из интерфейса_t.

Затем вы можете загрузить плагин, экземпляр интерфейса с помощью фабрики и удалять константы выглядит -

delete interface->object() 

И как object_t имеет виртуальный деструктор правильный разрушитель будет называться.

Нет проблем с тем, где вы удаляете объект под linux, его тонкое под окном, если все плагины/исполняемые файлы связаны с одним и тем же динамическим (dll) CRT.

+0

Сам термин «dll» подразумевает Windows, в Linux он бы сказал «так» (общий объект). Кроме того, все двоичные файлы, связанные с одним и тем же CRT, являются очень сложным требованием Если вы хотите написать плагин контекстного меню проводника, и Microsoft заявила: «Для обратной совместимости со старыми плагинами, которые мы все еще компилируем с помощью Visual C++ 4.0, вы должны также забыть об использовании исключений, шаблонов или любая другая современная функция C++ в вашем плагине ». –

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