Получение классов без виртуального деструктора в стороннем программном обеспечении

Мне предоставляется сторонняя библиотека с ее заголовком для использования. Теперь в этой библиотеке есть класс Base. Проблема с этим классом в том, что у него нет виртуального деструктора. Теперь, поскольку у меня нет стороннего кода, я не могу вносить изменения там.

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


Спасибо за ответ, похоже, у меня есть только 2 варианта.

1) поместить виртуальный деструктор в производный класс 2) использовать композицию.

Я планирую использовать подход № 1. Я планирую иметь производный класс-оболочку с виртуальным деструктором. А затем используйте этот производный класс-оболочку для дальнейшего вывода. Ниже приведен код.

//++ THIRD PARTY HEADER
class base
{
public:
    ~base(){ }
};
//-- THIRD PARTY HEADER



//++ MY CODE
// wrapper polymorphic base.
class polymorphic_base
{
public:    
    virtual ~polymorphic_base() { }
};

class derived1 : polymorphic_base
{
/// derived 1
};

class derived2 : polymorphic_base
{
/// derived 2
}


void foo(polymorphic_base *pb)
{
    // use pb
    // use pb
    delete pb;
}


//-- MY CODE

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


person stackoverflow    schedule 30.12.2012    source источник
comment
В общем, вам не повезло: если у них нет виртуального деструктора, это обычно означает, что авторы библиотеки не хотят, чтобы вы производились от их класса. Зачем вообще нужно извлекать (в отличие, скажем, от включения экземпляра в качестве члена данных?)   -  person Sergey Kalinichenko    schedule 30.12.2012
comment
Просто проверяю: подтвердили ли вы, что сам Base, возможно, не является производным от какой-то супербазы, в которой деструктор определен как виртуальный?   -  person jogojapan    schedule 30.12.2012
comment
Кто удаляет экземпляр?   -  person Yakk - Adam Nevraumont    schedule 30.12.2012
comment
@dasblinkenlight может быть, вы правы, автор, не хотите, чтобы этот класс был производным. Вы правы, я думаю, мне нужно изменить свой дизайн и вместо этого использовать Base в качестве композиции.   -  person stackoverflow    schedule 30.12.2012


Ответы (2)


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

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

В первом случае, поскольку у вас нет кода для этого базового класса, вы не можете преодолеть фиаско. Лучшее, что вы можете сделать, это рассмотреть отношения has-a, а не отношения is-a, и попытаться заставить их работать на вас.

person Alok Save    schedule 30.12.2012

С невиртуальным деструктором Base, если вам нужно поддерживать delete из Base*, вам просто не повезло.

В противном случае к

убедитесь, что объект правильно очищается при удалении объектов

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

Но вы уверены, что требование действительно буквально «когда объекты удаляются»? Потому что гораздо лучше было бы запретить динамическое размещение. Что вы можете сделать в коде, сделав практически непригодными то, что нужно new-выражению, например, функцию распределения (например, ограничив ее доступность), и что вы можете сделать еще проще, просто заявив в документации, что динамическое выделение не является поддерживается.

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

person Cheers and hth. - Alf    schedule 30.12.2012