2012-01-23 25 views
8
/*Child is inherited from Parent*/ 
class Parent { 
    public: 
    Parent() //Constructor 
    { 
     cout << "\n Parent constructor called\n" << endl; 
    } 
    protected: 
    ~Parent() //Dtor 
    { 
     cout << "\n Parent destructor called\n" << endl; 
    } 
}; 

class Child : public Parent 
{ 
    public: 
    Child() //Ctor 
    { 
     cout << "\nChild constructor called\n" << endl; 
    } 
    ~Child() //dtor 
    { 
     cout << "\nChild destructor called\n" << endl; 
    } 
}; 

int main() 
{ 
    Parent * p2 = new Child;   
    delete p2; 
    return 0; 
} 

Nếu tôi tạo Parent phá hủy ảo, thì tôi gặp lỗi, vậy mục đích của việc tạo một destructor ảo được bảo vệ là gì?Có cách nào để tạo một trình phá hủy được bảo vệ ảo không?

+1

Có lẽ chúng ta nên bắt đầu bằng "tại sao bạn nên bảo vệ dtor?". –

+4

Tại sao bạn lại muốn làm cho destructor ảo? Không nên * bạn * biết mục đích? Một destructor được bảo vệ có nghĩa là các đối tượng không nên bị phá hủy thông qua các con trỏ cơ sở, vì vậy mã trong 'main' là sai. – thiton

+0

Xem http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors – user998692

Trả lời

17

Chỉ cần đưa ra một ví dụ: Giả sử bạn có một lớp cơ sở thực hiện đếm tham chiếu. Bạn có addRef và phương thức release và bạn muốn đối tượng của mình bị hủy, nếu (và chỉ nếu) bộ đếm nội bộ bằng không thông qua cuộc gọi đến release.

Vì vậy, trước tiên bạn muốn bảo vệ chống phá hoại của mình (vì bạn chỉ muốn hủy đối tượng trong phạm vi relase).

Nếu bạn có kế hoạch bắt nguồn từ lớp học, bạn cũng muốn có destructor ảo của bạn, vì bạn cần một destructor ảo bất cứ khi nào bạn muốn phá hủy một đối tượng con thông qua một con trỏ đến một lớp cơ sở (cảm ơn @sharptooth cho gợi ý ...)

+2

Không, bạn cần một destructor ảo bất kể cho dù các lớp học có nguồn gốc yêu cầu bất kỳ sự phá hủy thêm, nếu không hành vi chỉ là không xác định. – sharptooth

+0

@sharptooth Phải, tôi không nghĩ về điều này. Cố định nó, cảm ơn vì đã chỉ ra! – MartinStettner

+0

Tôi thấy một số mã sử dụng thủ thuật này để buộc tất cả sự hủy diệt phải trải qua chức năng trình bao bọc kiểu C của người bạn (được xác định cho mỗi lớp dẫn xuất). Tôi đoán ý định tương tự nhưng bị mất theo sự bảo trì. – Muxecoid

4

protected: Base::~Base(); phải là ảo ít nhất nếu bạn (lập kế hoạch) xóa bất kỳ đối tượng nào có nguồn gốc từ Base trong phạm vi Base hoặc lớp dẫn xuất là Base.

+0

xóa mục này; đối với bất kỳ đối tượng con không xác định nào đã nhận được cảm ơn – tusharfloyd

+0

@ user1085822: Vì vậy, bạn cảm ơn tôi trong khi không chấp nhận câu trả lời của tôi. Bạn đang cố để nói với tôi cái gì thế? – bitmask

+0

Không nên chỉ là – ksb

5

Có, nếu bạn định làm delete this trong class Parent chức năng thành viên rất phổ biến khi triển khai IUnknown::Release() trong đối tượng COM.

+0

Tuyệt. Và cho rằng vấn đề bất kỳ lớp học có nguồn gốc khác nếu 'depete pBase;' attampted. – iammilind

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