Как вызвать деструктор производного класса в качестве приватного в следующей программе?

#include<iostream>

class base
{
   public:
       virtual ~base(){std::cout << "base\n";}
};
class derived : public base
{
   private:
        ~derived(){std::cout << "derived\n";} /* destructor is private */
};
int main()
{
      base *pt= new derived;
      delete pt;
}

Вышеупомянутая программа компилируется и работает нормально. Каким образом вызванный дескриптор производного класса является закрытым?

Ответ 1

Это произойдет не только с деструкторами.

Вы можете переопределить любую виртуальную публичную функцию с помощью частного.

#include<iostream>

class base
{
   public:
       virtual void x(){std::cout << "base\n";}
};
class derived : public base
{
   private:
        void x(){std::cout << "derived\n"; base::x();}
};
int main()
{
      base *pt= new derived;
      pt->x(); //OK
      //((derived *)pt)->x();  //error: ‘virtual void derived::x()’ is private
      derived *pt2= new derived;
      //pt2->x();  //error: ‘virtual void derived::x()’ is private
      ((base *)pt2)->x(); //OK
}

Поверхность/недостаток этого - вам придется использовать указатель на базу для доступа к этому методу. Эта функция является одним из способов отделить открытый API от индивидуальной реализации.

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

Ответ 2

Это может быть удивительно, но если вы думаете об этом, это совершенно логично.

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

Во время выполнения виртуальный деструктор вызывается. Поскольку оказывается, что указатель на базу действительно указывает на производный объект, следовательно, сначала нужно вызвать производный конструктор.
"Но это личное!" говорит вам. Это право, однако, во время работы нет понятия публичного/частного. Итак, опять же, нет причин для чего-то плохого. Ошибка генерируется.