簡體   English   中英

C ++析構函數問題

[英]C++ destructors question

關於下面的示例代碼,為什么基類的析構函數被調用兩次?

class Base {
public:
    Base() {
        std::cout << "Base::Base()" << std::endl;
    }

    ~Base() {
        std::cout << "Base::~Base()" << std::endl;
    }
};

class Derived : public Base {
public:
    Derived() {
        std::cout << "Derived::Derived()" << std::endl;
    }

    ~Derived() {
        std::cout << "Derived::~Derived()" << std::endl;
    }
};

int main() {
    Base a = Derived();
    return EXIT_SUCCESS;
}

以下是程序運行時輸出的示例:

Base::Base()
Derived::Derived()
Derived::~Derived()
Base::~Base()
Base::~Base()

發生的事情稱為切片。 使用Derived類型的對象初始化Base類型的對象。 由於任何Derived類型的對象都有一個Base類型的對象(稱為“基類子對象”),因此在整個程序中將存在兩個Base對象和一個Derived對象。 Derived對象(及其Base類型的Base類子對象)僅在初始化時存在,而剩余的Base對象存在直到main結束。

由於有兩個Base對象和一個Derived對象,因此您還將看到另外一個Base destructors運行。

正在使用復制構造函數。 如果要查看發生了什么,請檢查復制構造函數:

 Base( const Base & ) {
        std::cout << "Base::Base( const Base &)" << std::endl;
    }

和Derived類似。

請注意,這與析構函數不是虛擬的無關。

當你在main()Derived() ,它會創建一個臨時對象,然后將其復制到對象a中。 因此有兩個對象,因為析構函數被調用兩次。 另外,正如其他人指出你的基類析構函數應該是虛擬的。

因為你創建一個臨時類型的Derived之前拷貝構造a與它。 所以這基本上是發生了什么:

Derived d(); // Your temporary of type Derived is created
Base a(d); // The temporary is used to call a's copy constructor 
d.Derived::~Derived(); // The temporary is destroyed, calling both ~Derived and ~Base
a.Base::~Base(); // The nonvirtual destructor on a is called, so ~Base is called, but not ~Derived

因此除了開頭不必要的復制(編譯器可能優化掉)之外,實際的錯誤是~Base不是虛擬的。

編輯哎呀,完全錯過了litb指出的切片。 請改為閱讀他的回答:)

添加以下內容將使程序更加清晰:

 Base(const Base& base){
        std::cout << "Base::Base(const Base& base)" << std::endl;
 }

編譯器將自動為您創建一個復制構造函數。 通過自己定義,(並通過添加打印),您可以看到構造函數和析構函數的數量匹配

Base::Base()
Derived::Derived()
Base::Base(const Base& base)
Derived::~Derived()
Base::~Base()
Base::~Base()

你需要一個虛擬的析構函數

你有一個堆棧變量和一個臨時變量 - 總共構造了兩個對象 - 因此析構函數被調用兩次是合乎邏輯的。

1)構建Derived類型的臨時對象(調用Derived :: Derived()和Base :: Base())

2)臨時對象被復制到“a”

3)銷毀臨時對象(Derived :: ~Derived()和Base :: ~Base()被調用)

4)返回EXIT_SUCCESS;

5)“a”被銷毀,因此調用Base :: ~Base()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM