Здравствуйте, Nikopol, Вы писали:
N>Если делать деструктор защищённым, то это ровным счётом ничего не меняет.
N>Компилятор это проглатывает.
N>Если сделать приватным, то тогда компилятор ругается на попытки объявить деструкторы у наследников.
Разумеется. И это не глюки.
Просто, если у наследника деструктор не определён явно, то его определяет компилятор, причём публичным. И тут — лишь бы деструктор базы был доступен наследнику.
class B1
{
~B1() {} // недоступен потомкам
};
class D11 : public B1
{
// деструктор не определён явно, и если его не вызывают (скалярно или по delete), то не определён вообще
// объект невозможно разрушить
};
class D12 : public B1
{
~D12() {} // ошибка: деструктор предка недоступен
};
void foo1()
{
D11 d; // ошибка: требуется деструктор
D11* pd = new D11(); // сколько угодно
delete pd; // ошибка: требуется деструктор
delete (B*)pd; // ошибка: деструктор приватный; без неё был бы баг (недоразрушение потомка)
}
class B2
{
protected:
~B1() {} // доступно потомкам
};
class D21
{
// неявно определённый деструктор будет публичным
};
class D22
{
protected:
~D22() {} // только таким способом мы прячем деструктор
};
void foo2()
{
D21 d1; // в лучшем виде
D22 d2; // ошибка
D22 *p = new D22;
delete p; // ошибка
}
class B3
{
virtual ~B3() {} // приватный деструктор, но из-за врождённой багофичи С++ он доступен для перекрытия
};
class D31
{
// Неявно определённый деструктор будет виртуальным и публичным.
// Поскольку перегрузка взламывает права доступа, деструктор предка стал доступен деструктору потомка
};
class D32
{
protected:
~D32() {} // только таким способом мы прячем деструктор; он, разумеется, продолжает быть виртуальным
};