【C++學習】構造函數和析構函數順序

總體說明:兩個類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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章