2012-02-02 24 views
7

Tôi cần khai báo phương thức hoàn thiện finalize() cho tất cả hậu duệ của lớp cơ sở Base, nên được gọi trong quá trình hủy và ý định của tôi là gọi số tinh khiết từ số ~Base(), nhưng C++ cấm như vậy. Vì vậy, câu hỏi của tôi làGọi phương thức ảo từ trình phá hủy - giải pháp thay thế?

Làm thế nào chúng ta có thể bắt chước con cháu thực hiện một số công việc hoàn thiện đúng cách và được xác định sơ bộ?

Đó mã không thể được biên dịch:

#include <QDebug> 
class Base { 
     public: 
      Base(){} 
      virtual ~Base(){ 
       qDebug("deleting b"); 
       finalize(); 
      } 
      virtual void finalize() = 0; 

    }; 

class A : public Base 
    { 
    public: 
     A(){} 
     ~A(){} 
     void finalize(){qDebug("called finalize in a");} 
    }; 

    int main(int argc, char *argv[]) 
    { 
     Base *b = new A; 
     delete b; 
    } 

Nếu tôi làm Base::finalize() không tinh khiết ảo, nó được gọi là từ ~Base() mà không cử cho con vì nó đã được đã destructed.

Tôi có thể gọi finalize() từ destructor của trẻ nhưng câu hỏi là làm thế nào để buộc phải làm điều đó. Nói cách khác, câu hỏi của tôi là: có thể bắt buộc những người sẽ viết hậu duệ của lớp Base để sử dụng phương pháp hoàn thiện, theo cách khác hơn là bình luận nó trong một tài liệu? :)

Trả lời

7

Các cơ cấu phá hủy là nơi thích hợp để giải phóng tài nguyên có được, nhưng mỗi lớp chịu trách nhiệm giải phóng tài nguyên của riêng mình. Tài nguyên được mua bởi class A không nên (và chỉ có thể không) được phát hành bởi class Base.

Xác định hàm hủy ảo cho phép class A 's destructor được gọi khi xóa một con trỏ đến class Base trỏ đến một đối tượng class A

Base* p = new A; 
delete p; // Both A and Base destructors are sequencially called! 

Vì vậy, để đạt được nguồn phát hành thích hợp, bạn chỉ cần có để phát hành mỗi lớp' tài nguyên tại của nó riêng của destructor.

+1

Ok, tôi hiểu rồi, nhưng câu hỏi của tôi là: có thể bắt buộc những người sẽ viết hậu duệ của lớp Base để sử dụng phương thức hoàn thiện, hay không, theo cách khác hơn là bình luận nó trong tài liệu? :) –

+1

Có thể xảy ra nhưng bạn có thể gặp lỗi trình biên dịch hoặc lỗi thời gian chạy, bởi vì vào thời điểm phá hủy 'Base' được gọi, hàm hủy' A' đã được gọi nên không có đối tượng 'A' trên đó gọi phương thức 'finalize()' của bạn. –

+1

Tôi đã sử dụng mã mẫu của bạn và đã xác định 'finalize()' cho 'Base', do đó làm cho nó thuần ảo (không thuần túy). Nó biên dịch, nhưng xem những gì bạn nhận được từ việc thực hiện của nó http://ideone.com/opDXc –

3

Đó là những gì một destructor ảo dành cho:

class A 
{ 
public: 
    virtual ~A() {} 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
}; 

Khi một đối tượng kiểu B bị phá hủy, cho dù từ một con trỏ đến một B hoặc một con trỏ đến một A, cả destructors sẽ gọi là. Trước tiên, B::~B() và sau đó A::~A().

+0

@DmitryKachko chỉ cần viết một cuộc gọi để "hủy gửi" trong mỗi lần hủy mà bạn muốn 'hủy gửi' xảy ra –

+0

Chắc chắn tôi có thể làm điều đó, nhưng tôi không thể bắt buộc những người sẽ sử dụng lớp A làm cơ sở –

+0

Cảm ơn bạn đã câu trả lời! Làm thế nào nó có thể giúp tôi? Tôi có hàm void unsubmit() nên gọi trong mỗi hậu duệ của A trong quá trình hủy diệt. Thực hiện Unsubmit là khác nhau cho mỗi người trong số họ. - –

1

Làm cho trình phá hủy lớp cơ sở thuần ảo với một phần nội dung, nên làm chính xác những gì bạn muốn.

+1

Tại sao ảo thuần túy? –

+0

Để buộc các lớp học có nguồn gốc khai báo và thực hiện một destructor của riêng mình. –

+0

Ồ, tôi không thấy cơ sở đó là trừu tượng (có thể là bản chỉnh sửa sau). –

0

Tại sao không sử dụng desctructor của Base? Đó là những gì là destructors được thực hiện cho.

Tìm kiếm RAII và khám phá một trong những điều tốt nhất trong C++.

Hầu hết mọi người thường sử dụng các ngôn ngữ khác đều phải khám phá điều này. Quản lý tài nguyên bằng C++ hoàn toàn khác với hầu hết các ngôn ngữ máy tính khác

+0

RAII phải làm gì với câu hỏi của anh ấy? –

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