попробуйте выполнить следующую команду:
pip install setuptools==28.8.0
Нет, деструкторы называют автоматически в обратном порядке конструкции. (Базовые классы в последний раз). Не называйте деструкторы базового класса.
Нет Вы не должны называть основной деструктор, основной деструктор всегда называет для Вас полученный деструктор. См. мой связанный ответ здесь для порядка разрушения.
Для понимания, почему Вы хотите виртуальный деструктор в базовом классе, см. код ниже:
class B
{
public:
virtual ~B()
{
cout<<"B destructor"<<endl;
}
};
class D : public B
{
public:
virtual ~D()
{
cout<<"D destructor"<<endl;
}
};
Когда Вы делаете:
B *pD = new D();
delete pD;
Затем, если бы у Вас не было виртуального деструктора в B, то только ~B () был бы назван. Но так как у Вас есть виртуальный деструктор, первый ~D () назовут, затем ~B ().
Что другие сказали, но также и обратите внимание, что Вы не должны объявлять деструктор, виртуальный в производном классе. После того как Вы объявляете виртуальный деструктор, как Вы делаете в базовом классе, все полученные деструкторы будут виртуальными, объявляете ли Вы их так или нет. Другими словами:
struct A {
virtual ~A() {}
};
struct B : public A {
virtual ~B() {} // this is virtual
};
struct C : public A {
~C() {} // this is virtual too
};
Нет. В отличие от других виртуальных методов, где Вы явно назвали бы Базовый метод от Полученного для 'объединения вызова в цепочку', компилятор генерирует код для вызова деструкторов в обратном порядке, в котором вызвали их конструкторов.
Деструкторы в C++ автоматически становятся названными в порядке их конструкций (Полученный затем Основа) только, когда деструктор Базового класса объявляется virtual
.
В противном случае затем только деструктор базового класса вызывается во время удаления объекта.
Пример: Без виртуального Деструктора
#include <iostream>
using namespace std;
class Base{
public:
Base(){
cout << "Base Constructor \n";
}
~Base(){
cout << "Base Destructor \n";
}
};
class Derived: public Base{
public:
int *n;
Derived(){
cout << "Derived Constructor \n";
n = new int(10);
}
void display(){
cout<< "Value: "<< *n << endl;
}
~Derived(){
cout << "Derived Destructor \n";
}
};
int main() {
Base *obj = new Derived(); //Derived object with base pointer
delete(obj); //Deleting object
return 0;
}
Вывод
Base Constructor
Derived Constructor
Base Destructor
Пример: С Основным виртуальным Деструктором
#include <iostream>
using namespace std;
class Base{
public:
Base(){
cout << "Base Constructor \n";
}
//virtual destructor
virtual ~Base(){
cout << "Base Destructor \n";
}
};
class Derived: public Base{
public:
int *n;
Derived(){
cout << "Derived Constructor \n";
n = new int(10);
}
void display(){
cout<< "Value: "<< *n << endl;
}
~Derived(){
cout << "Derived Destructor \n";
delete(n); //deleting the memory used by pointer
}
};
int main() {
Base *obj = new Derived(); //Derived object with base pointer
delete(obj); //Deleting object
return 0;
}
Вывод
Base Constructor
Derived Constructor
Derived Destructor
Base Destructor
рекомендуется объявить деструктор базового класса как virtual
иначе, он вызывает неопределенное поведение.
Ссылка: Виртуальный Деструктор