Есть ли смысл делать виртуальный защищенный деструктор? - PullRequest
10 голосов
/ 23 января 2012
/*Child is inherited from Parent*/
class Parent {  
  public:  
    Parent () //Constructor
    {
        cout << "\n Parent constructor called\n" << endl;
    }
  protected:
    ~Parent() //Dtor
    {
        cout << "\n Parent destructor called\n" << endl;
    }
};

class Child : public Parent 
{
  public:
    Child () //Ctor
    {
        cout << "\nChild constructor called\n" << endl;
    }
    ~Child() //dtor
    {
        cout << "\nChild destructor called\n" << endl;
    }
};

int main ()
{
    Parent * p2 = new Child;          
    delete p2;
    return 0;
}

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

Ответы [ 4 ]

18 голосов
/ 23 января 2012

Просто приведу один пример: скажем, у вас есть базовый класс, который реализует подсчет ссылок.У вас есть методы addRef и release, и вы хотите, чтобы ваш объект был уничтожен, если (и только если) внутренний счетчик достигает нуля при вызове release.

Итак, сначала вы хотите защитить свой деструктор (так как вы хотите уничтожить объект только из relase).

Если вы планируете наследовать от своего класса, вы также хотите иметь виртуальный деструктор, поскольку вам нужен виртуальный деструктор, когда вы хотите уничтожить дочерний объект через указатель на базовый класс (спасибо @sharptooth занамек ...)

5 голосов
/ 23 августа 2018

В основных руководящих принципах C ++ есть запись *1002*, посвященная этой конкретной теме:

C.35: деструктор базового класса должен быть публичным и виртуальным,или защищенный и не виртуальный

Причина Для предотвращения неопределенного поведения.Если деструктор является общедоступным, то вызывающий код может попытаться уничтожить объект производного класса с помощью указателя базового класса, и результат не определен, если деструктор базового класса не является виртуальным.Если деструктор защищен, то вызывающий код не может быть уничтожен через указатель базового класса, и деструктор не должен быть виртуальным;он должен быть защищен, а не закрыт, чтобы производные деструкторы могли вызывать его.Как правило, автор базового класса не знает, какое действие необходимо выполнить после уничтожения.

Таким образом, деструктор не должен быть виртуальным, если он защищен.Однако есть исключение:

Исключение Мы можем представить один случай, когда вам может понадобиться защищенный виртуальный деструктор: когда объект производного типа (и только такого типа).Тип) должно быть разрешено уничтожить другой объект (не сам) через указатель на базу.Однако на практике мы не видели такого случая.

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

5 голосов
/ 23 января 2012

Да, если вы собираетесь выполнять delete this в class Parent функциях-членах, что очень часто встречается при реализации IUnknown::Release() в COM-объектах.

4 голосов
/ 23 января 2012

protected: Base::~Base(); должно быть виртуальным, по крайней мере, если вы (планируете) удалить любые объекты, полученные из Base в Base или производный класс Base.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...