Чистый виртуальный деструктор в интерфейсе - PullRequest
1 голос
/ 15 июня 2010

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

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

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

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

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

РЕДАКТИРОВАТЬ: Опять же, у меня нет противоречий управления памятью, это все внутри DLL. Но правильный деструктор просто не называется.

Ответы [ 3 ]

4 голосов
/ 15 июня 2010

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

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

1 голос
/ 15 июня 2010

Вот как я решил вашу конкретную проблему для динамически загружаемых классов 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 и другие утилиты типов, например, у моего базового объекта есть spawn (), copy (), object_name ().

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

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

delete interface->object()

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

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

0 голосов
/ 15 июня 2010

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

...