2012-10-17 64 views
5

Tại sao tất cả các trình phá hủy, ~D(), ~C(), ~B(), ~A() được gọi trong ví dụ bên dưới?Tại sao destructor lớp cơ sở được gọi là đối tượng dẫn xuất khi destructor của lớp dẫn xuất là không ảo?

Chỉ có một trình phá hủy ảo: số của A.

Đây là mã:

#include<iostream> 
using namespace std; 

class A 
{ 
public: 
    virtual ~A() 
    { 
    cout<<"destruct A\n"; 
    } 

}; 
class B:public A 
{ 
public: 
    ~B() 
    { 
    cout<<"destruct B\n"; 
    } 
}; 
class C:public B 
{ 
public: 
    ~C() 
    { 
    cout<<"destruct C\n"; 
    } 
}; 
class D:public C 
{ 
public: 
    ~D() 
    { 
    cout<<"destruct D\n"; 
    } 
}; 

int main() 
{ 
    A* ptr = new D(); 
    delete ptr; 
    return 0; 
} 
+1

Vì đó là những gì các quy tắc của ngôn ngữ nói sẽ xảy ra. – juanchopanza

Trả lời

7

Khi destructor A 's được khai báo virtual, destructors của tất cả các lớp thừa kế cũng là virtual, ngay cả khi họ không khai báo rõ ràng như vậy .. Vì vậy, hành vi bạn thấy được chính xác những gì được mong đợi

+1

@spin_eight một 'D' được truy cập thông qua một con trỏ đến' A', đó là những gì xóa được gọi là trên. Nếu destructor 'A' không phải là ảo, chỉ có' ​​~ A() 'sẽ được gọi. Bạn có thể dễ dàng tự kiểm tra. – juanchopanza

+0

Vâng, cảm ơn bạn! –

6

Trình tự phá hủy trong các đối tượng có nguồn gốc đi chính xác điều ngược lại tự xây dựng: đầu tiên destructors của hầu hết các nguồn gốc lớp được gọi và sau đó là destructor của các lớp cơ sở.

Một destructor có thể được định nghĩa là ảo ảo hoặc thậm chí thuần túy. Bạn sẽ sử dụng một destructor ảo nếu bạn đã bao giờ mong đợi một lớp dẫn xuất là bị phá hủy thông qua một con trỏ đến lớp cơ sở. Điều này sẽ đảm bảo rằng destructor của các lớp thừa kế hầu hết sẽ được gọi là:

A* b1 = new B;//if A has a virtual destructor 
delete b1;//invokes B's destructor and then A's 

A* b1 = new B;//if A has no virtual destructor 
    delete b1;//invokes A's destructor ONLY 

Nếu A không có một destructor ảo, xóa b1 qua một con trỏ loại A sẽ chỉ gọi của một destructor . Để thực thi sự kêu gọi của destructor B trong trường hợp này chúng ta phải có chỉ định của một destructor như ảo:

virtual ~A(); 

REFERENCE

+0

"thậm chí thuần ảo" - khi nào để ngăn chặn lỗi thời gian chạy, bạn phải tạo cơ thể cho destructor ảo tinh khiết để phân bổ địa chỉ trong bảng ảo cho destructor đó, không chỉ nullptr –

0

Như @juanchopanza nói - tuyên bố destructor cơ sở phương tiện ảo tất cả con cháu có ảo destructors. Tính năng ảo được kế thừa này là giống nhau cho bất kỳ phương thức nào, không chỉ là các trình phá hủy. Đó là lý do tại sao tôi đã phỏng vấn những người không biết từ khóa đã làm gì bởi vì họ đã từng phải ghi đè lên các phương thức có nguồn gốc từ một khuôn khổ, vì vậy tất cả chúng đều là ảo (thở dài).

Các vấn đề liên quan