總體說明:兩個類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