总体说明:两个类X和Y,Y继承自X。
- 通过基类指针delete 派生类对象,只会调用基类的析构函数。派生类的析构函数不会调用。 这是一个比较容易写出bug的一个地方。通常做法是,如果基类包含虚函数,那么析构函数必须设置成虚函数。
- 其它情况,派生类析构函数会先调用,然后调用基类析构函数。
- 问题:如果对于任何场景,析构函数都写成虚函数,是否可行?
无虚函数
栈上对象
class X {
public:
X() { cout << "X ctor" << endl; }
~X() { cout << "X dtor" << endl; }
};
class Y : public X {
public:
Y() { cout << "Y ctor" << endl; }
~Y() { cout << "Y dtor" << endl; }
};
int main()
{
Y y;
return 0;
}
X ctor
Y ctor
Y dtor
X dtor
堆上对象
class X {
public:
X() { cout << "X ctor" << endl; }
~X() { cout << "X dtor" << endl; }
};
class Y : public X {
public:
Y() { cout << "Y ctor" << endl; }
~Y() { cout << "Y dtor" << endl; }
};
int main()
{
Y *ptr = new Y();
delete ptr;
return 0;
}
X ctor
Y ctor
Y dtor
X dtor
有虚函数
析构函数不为虚
栈上对象
class X {
public:
X() { cout << "X ctor" << endl; }
~X() { cout << "X dtor" << endl; }
virtual void func() { cout << "virtual func in X" << endl; }
};
class Y : public X {
public:
Y() { cout << "Y ctor" << endl; }
~Y() { cout << "Y dtor" << endl; }
void func() override { cout << "virtual func in Y" << endl; }
};
int main()
{
Y y;
return 0;
}
X ctor
Y ctor
Y dtor
X dtor
堆上对象
使用基类指针指向派生类
class X {
public:
X() { cout << "X ctor" << endl; }
~X() { cout << "X dtor" << endl; }
virtual void func() { cout << "virtual func in X" << endl; }
};
class Y : public X {
public:
Y() { cout << "Y ctor" << endl; }
~Y() { cout << "Y dtor" << endl; }
void func() override { cout << "virtual func in Y" << endl; }
};
int main()
{
X *ptr = new Y();
delete ptr;
return 0;
}
X ctor
Y ctor
X dtor
使用派生类指针指向派生类
class X {
public:
X() { cout << "X ctor" << endl; }
~X() { cout << "X dtor" << endl; }
virtual void func() { cout << "virtual func in X" << endl; }
};
class Y : public X {
public:
Y() { cout << "Y ctor" << endl; }
~Y() { cout << "Y dtor" << endl; }
void func() override { cout << "virtual func in Y" << endl; }
};
int main()
{
Y *ptr = new Y();
delete ptr;
return 0;
}
X ctor
Y ctor
Y dtor
X dtor
析构函数为虚
栈上对象
和析构函数不为虚的时候相同。
堆上对象
使用基类指针指向派生类
class X {
public:
X() { cout << "X ctor" << endl; }
virtual ~X() { cout << "X dtor" << endl; }
virtual void func() { cout << "virtual func in X" << endl; }
};
class Y : public X {
public:
Y() { cout << "Y ctor" << endl; }
~Y() override { cout << "Y dtor" << endl; }
void func() override { cout << "virtual func in Y" << endl; }
};
int main()
{
X *ptr = new Y();
delete ptr;
return 0;
}
X ctor
Y ctor
Y dtor
X dtor
使用派生类指针指向派生类
class X {
public:
X() { cout << "X ctor" << endl; }
virtual ~X() { cout << "X dtor" << endl; }
virtual void func() { cout << "virtual func in X" << endl; }
};
class Y : public X {
public:
Y() { cout << "Y ctor" << endl; }
~Y() override { cout << "Y dtor" << endl; }
void func() override { cout << "virtual func in Y" << endl; }
};
int main()
{
Y *ptr = new Y();
delete ptr;
return 0;
}
X ctor
Y ctor
Y dtor
X dtor