наследование — защита деструкторов в абстрактном базовом классе не наследуется в C ++?

Я обнаружил утечку памяти в моем коде, вызванную вызовом только деструктора базового класса для объектов. Эта проблема понята: я уже добавил virtual деструктору класса интерфейса MyÌnterface, Меня озадачивает то, что компилятор явно создал стандартный деструктор для моего вспомогательного класса MyHelperэто в конечном итоге называется. Я попробовал это с двумя разными компиляторами.

Это меня очень удивило, так как я заметил, что большинство реализаций по умолчанию не создаются, если члены или базовые классы вводят ограничения. Почему защита деструктора не передается по наследству?

#include <iostream>

class MyInterface
{
public:
virtual void doSomethingUseful()=0;
// a lot more functions declared omitted
virtual void doSomethingElse()=0;
virtual void doSomethingIndividual()=0;
protected:
/// protected destructor to forbid calling it on interfaces
~MyInterface() {} // HERE the virtual is clearly missing
};

/// a common base that defaults most functions implementations
class MyHelper: public MyInterface
{
public:
void doSomethingUseful() {}
// a lot more default implementations omitted
void doSomethingElse() {}
};

class SomeImplementation: public MyHelper
{
public:
SomeImplementation()
{
std::cout << "SomeImplementation ctr" << std::endl;
}
~SomeImplementation()
{
std::cout << "SomeImplementation dtr" << std::endl;
}
void doSomethingIndividual()
{
std::cout << "SomeImplementation did it." << std::endl;
}
};

/// user of MyInterface cannot delete object mi passed as parameter
int deleteSafeUsage(MyInterface& mi)
{
mi.doSomethingIndividual();
// would cause a compiler error: delete &mi;
}

/// usage restricted to MyHelper level, only exception is object creation
int testIt()
{
MyHelper* h = new SomeImplementation;
deleteSafeUsage(*h);
delete h; // <- HERE the memory leak happens!
}

Вот вывод приведенного выше примера кода, который «показывает» недостающие SomeImplementation ctr:

SomeImplementation ctr
SomeImplementation did it.

2

Решение

Конструкторы и деструкторы не наследуются. Так почему же их видимость наследуется?

Вы можете проверить стандарт, чтобы быть уверенным, но cppreference говорит это, акцент мой:

Если пользовательский деструктор не предоставлен для типа класса (struct, class или union), компилятор всегда объявляет деструктор как встроенный общественности член своего класса.

Итак, если вы хотите ~MyHelper Чтобы быть защищенным, вы должны объявить это явно.

Обратите внимание, что если MyInterface был виртуальный деструктор, неявный деструктор MyHelper также будет виртуальным. Так что этот аспект унаследован, в некотором роде. Опять же, вы хотите обратиться к стандарту, если вы хотите быть уверенным, но это упоминается в c ++ faq lite

Для полноты вот Херб Саттерс руководство о том, как использовать виртуальность в целом и с деструкторами.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]