2009-05-05 32 views
14

Tôi đã có một tập hợp lớn các lớp thừa kế (tiêu chí) kế thừa từ một lớp cơ sở (tiêu chí). Dưới đây là criterion của mãVirtual Destructors mặc định trong C++

class criterion 
{ 
public: 
    virtual unsigned __int32 getPriorityClass() const = 0; 
    virtual BOOL include(fileData &file) const = 0; 
    virtual void reorderTree() = 0; 
    virtual unsigned int directoryCheck(const std::wstring& directory) const = 0; 
    virtual std::wstring debugTree() const = 0; 
}; 

Một số ví dụ về các lớp học có nguồn gốc từ một này:

class fastFilter : public criterion 
{ 
public: 
    void reorderTree() {}; 
    unsigned int directoryCheck(const std::wstring& /*directory*/) const { return DIRECTORY_DONTCARE; }; 
    unsigned __int32 getPriorityClass() const { return PRIORITY_FAST_FILTER; }; 
}; 

class isArchive : public fastFilter 
{ 
public: 
    BOOL include(fileData &file) const 
    { 
     return file.getArchive(); 
    } 
    std::wstring debugTree() const 
    { 
     return std::wstring(L"+ ISARCHIVE\n"); 
    }; 
}; 

Vì tôi không có một destructor đây ở tất cả, nhưng tuy nhiên điều này được coi là một lớp cơ sở , tôi có cần chèn một destructor ảo rỗng không như thế này ?:

virtual void ~criterion() = 0; 

Nếu khai báo phá hủy ảo đó là cần thiết, tất cả các lớp trung gian cũng cần một hay không? I E. fastFilter sẽ ở trên cần một destructor ảo là tốt?

+0

Ở trên không phải là trình phá hủy trống. Đó là một destructor cũng là một chức năng ảo tinh khiết. Điều này không liên quan gì đến việc trống rỗng, và trên thực tế, destructor là đặc biệt ở chỗ nó phải luôn luôn có một định nghĩa ngay cả khi nó thuần ảo. –

Trả lời

37

Có - lớp cơ sở cần một trình phá hủy ảo, ngay cả khi nó trống. Nếu điều đó không được thực hiện, thì khi một đối tượng dẫn xuất của một đối tượng thông qua một con trỏ/tham chiếu cơ sở, đối tượng thành viên của đối tượng dẫn xuất sẽ không có cơ hội để tiêu diệt chúng một cách chính xác.

Các lớp có nguồn gốc không cần phải khai báo hoặc xác định hàm hủy riêng của chúng trừ khi chúng cần một thứ gì đó khác với hành vi phá hủy mặc định.

23

Khuyến cáo là để chèn

virtual ~criterion() {} 

để tránh việc xóa bỏ một vấn đề cơ bản con trỏ lớp. Nếu không, bạn sẽ bị rò rỉ bộ nhớ như destructors lớp học có nguồn gốc sẽ không được gọi.

criterion *c = new fastFilter(); 
delete c; // leaks 
+1

Có lý do nào để sử dụng một destructor trống trên một virtual virtual? –

+0

Nevermind ... được trả lời bởi người khác :) –

+1

Không phải là tiêu chí 'virtual ~() noexcept {}' đẹp hơn? – user1095108

12

Bạn không cần phải thực hiện trừu tượng destructor, chỉ cần cung cấp cho nó một thực hiện trống:

virtual ~criterion() { } 

Bằng cách này bạn không bị buộc phải thực hiện nó trong mọi tầng lớp trẻ, nhưng vẫn mỗi chúng sẽ có một destructor ảo (kế thừa).

7

Một thay đổi nhỏ so với những gì người khác đã trả lời:

Thay vì

virtual void ~criterion() = 0; 

phiên bản yêu cầu là:

virtual ~criterion() {} //Note: Removed void as destructors not allowed 
          // a return type 

Để biết thêm về destructor ảo có một cái nhìn tại đây liên kết từ Câu hỏi thường gặp When should my destructor be virtual?

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