Подтвердить что ты не робот

Как удалить объект типа полиморфного класса, который не имеет виртуального деструктора

Я получаю следующую ошибку, когда пытаюсь скомпилировать код из стороннего SDK.

*Description    Resource    Path    Location    Type
deleting object of polymorphic class type ‘Vendor_sys::VendorCode’ which has non-virtual destructor might cause undefined behaviour [-Werror=delete-non-virtual-dtor]   PnServer.cpp    /PCounter   line 467    C/C++ Problem*

Я не знаю, возможно ли удовлетворить это условие только частичным знанием SDK поставщика, где большая часть тяжелого подъема выполняется в DLL или библиотечном объекте.

Моя среда сборки - Eclipse Juno с gpp.

Я искал в Google сообщение об ошибке и не нашел экземпляров этой ошибки.

Итак, если я не могу изменить часть черного ящика кода поставщика, каковы мои варианты?

Вот код, который не работает во время процесса make:

delete pData->unit;
4b9b3361

Ответ 1

Собственно, я удалил ключ -Werror из компиляции и скомпилировал программу.

Теперь сообщения являются просто предупреждениями.

Я отправлю отчет об ошибке поставщику.

Ответ 2

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

Если вам не нужны полиморфные указатели, включите объект этого типа в свой класс и делегируйте функции-члены, которые вы хотели наследовать.

class my_class {
private:
    evil_class evil;
public:
    virtual ~my_class() {/* stuff */}
    virtual int member() { return evil.member(); }
};

Ответ 3

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

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

Ответ 4

Это предупреждение создается, когда базовый класс имеет виртуальные функции-члены, но не виртуальный dtor. Это ошибка. Если у вас нет кода, то вы ничего не можете сделать, кроме того, что убедитесь, что вы вручную отменяете любые ресурсы вашего подкласса. Как и в пользовательской функции cleanup(), которую вы вызываете вручную, перед удалением объекта.

Другим вариантом является static_cast его в правильный класс. Обратите внимание, что dynamic_cast (который требует затрат времени выполнения и требует RTTI) не требуется. В этом случае компилятор может получить отношения типа очень хорошо при компиляции.

Конечно, если объект удаляется где-то еще, а не частью вашего кода, то вам не повезло. В этом случае убедитесь, что ваш подкласс ничего не выделяет. Таким образом, невозможно просачиваться даже тогда, когда деструктор не вызывается.

Ответ 5

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

Если сама библиотека не создает подклассы этого объекта, вы можете получить необходимый эффект, объявив подкласс для этого объекта и используя этот объект в качестве базового класса.

class NotGoodBase {
 ~NotGoodBase(); // Non-virtual destructor.  Possibly added by compiler.
};

class UseThisAsBase : public NotGoodBase {
 virtual ~UseThisAsBase(); // Virtual destructor.
};

Вы можете использовать указатели типа UseThisAsBase в любом месте, где вы могли бы использовать NotGoodBase, кроме тех мест, где вам нужно иметь LValue типа NotGoodBase, например, назначение или передачу переменной по ссылке.

Ответ 6

В этом случае вам нужно добавить виртуальный деструктор в свой класс, а не удалить флаг компиляции здесь.

например. для класса Myclass эта ошибка подходит, затем добавьте

virtual ~Myclass(){}

Попробуйте эту душу, она будет работать нормально.