2010-10-14 40 views
6

Trong destructor của tôi, tôi phải làm sạch một vài tài nguyên. Giả sử tôi có ba cuộc gọi để xóa tài nguyên có thể ném. Vì nó không phải là tốt cho phép một ngoại lệ để lại một destructor, những gì nên được mẫu thiết kế của tôi? Rõ ràng cách dưới đây không thể mở rộng được.Ngoại lệ trong destructor

Cảm ơn.

class B::~B(){ 

try{ 
    clearResourceA() 
} 
catch{ 
    try{ 
     clearResourceB(); 
     } 
    catch{ 
     clearResourceC(); 
    } 
    clearResourceC(); 
} 
clearResourceB(); 
    . 
    . 
} 
+0

Đó là * chắc chắn * không thể mở rộng. Cố gắng quản lý chỉ ba tài nguyên, bạn đã có lỗi logic. – nobar

Trả lời

2

Chụp bất kỳ thứ gì có thể ném vào phá hủy của bạn với một nắm bắt (tức là, bắt (...)) và cố hết sức để xử lý các trường hợp ngoại lệ được ném. Hãy chắc chắn rằng không có ngoại lệ lan truyền ra khỏi destructor, mà catch-all sẽ giúp bạn ngăn chặn.

10

Tại sao không:

try{clearResourceA();} catch(...){} 
try{clearResourceB();} catch(...){} 
try{clearResourceC();} catch(...){} 
0
try 
{ 
    ClearResourceA(); 
} 
catch(...) 
{ 
    ExceptionWasThrown(); 
} 
try 
{ 
    ClearResourceB(); 
} 
catch(...) 
{ 
    ExceptionWasThrown(); 
} 
... 
+0

Offtop: Làm thế nào tôi có thể thực thi thụt đầu dòng? –

+0

Sử dụng nút "mã", không phải các dấu tích sau. Nút mã có 101010 trên đó. Nhập mã của bạn (thụt vào), đánh dấu mã, sau đó nhấn nút mã. – Starkey

+0

@Starkey: Rất tiếc, hôm nay không có các nút hoặc bản xem trước đó. Tôi hỏi về meta nhưng vẫn đang chờ trả lời –

5

đóng gói mỗi tài nguyên trong một lớp học mà xóa chúng trong destructor của nó (với một thử xung quanh/catch):

struct ProperlyManagedA { 
    // some means of using the resource - a rudimentary way is this: 
    A &getA() { return a; } 
    const A &getA() const { return a; } 
    // cleanup 
    ~ProperlyManagedA() { 
     try { 
      a.clear(); // whatever it is ClearResourceA actually does 
     } catch (...) {} 
    } 
    private: 
    A a; 
} 

Một shared_ptr với một tuỳ chỉnh deleter là một cách để đạt được điều này mà không cần phải tạo toàn bộ lớp cho từng loại tài nguyên.

Bạn có thể cải thiện việc loại bỏ ngoại lệ (ví dụ: ghi nhật ký sự cố), tùy thuộc vào nội dung được ném.

Thậm chí tốt hơn, sửa đổi tài nguyên A, B và C để chúng tự rõ ràng trong các trình phá hủy của riêng chúng. Điều đó có thể là không thể, mặc dù.

Dù bằng cách nào, bạn có thể đặt nhiều tài nguyên như vậy vào một lớp đơn tùy ý, mà không thêm bất kỳ mã nào vào trình phá hủy của lớp. Đây là "khả năng mở rộng". Toàn bộ quan điểm của RAII, là mỗi người dùng của một tài nguyên không cần phải viết mã dọn dẹp để sử dụng tài nguyên một cách chính xác.

+1

Sắp xếp tốt. Mục đích của RAII là dọn dẹp tất cả được thực hiện trong destructors của bạn, do đó bạn không gọi xóa hoặc freeHandle hoặc bất cứ chức năng bên trong các cơ quan của mã của bạn. Vấn đề chính ở đây là mã làm sạch nói chung không nên ném ở nơi đầu tiên. – CashCow

+0

@CashCow: "dọn dẹp là tất cả được thực hiện trong các destructors của bạn" - tốt, nếu các nguồn lực được thiết kế với nguyên tắc RAII, sau đó dọn dẹp được thực hiện trong destructor của tài nguyên. Nếu tôi phải tự viết lớp RAII, thì phải thừa nhận đó là thứ hủy diệt của tôi. Nhưng bất cứ ai viết nguồn tài nguyên RAII, người sử dụng tài nguyên RAII đó không phải viết hoặc gọi rõ ràng mã dọn dẹp. Đó là ý tôi là "người dùng". –

+0

cảm ơn, tôi đã phát điên khi nhìn vào các gợi ý khác:/ –

2

Bạn cũng có thể bọc các hàm ClearResources của mình để đảm bảo chúng không bao giờ ném. Tại sao họ có thể ném đi?

+0

Một số loại tuôn ra (hoặc các I/O khác) là lý do thông thường. –

1

Vì bạn đã hỏi về mẫu thiết kế Tôi sẽ nói quy tắc ngón tay cái nào tôi sử dụng với thành công. Tất cả chức năng có chức năng dọn sạch/chấm dứt nên KHÔNG BAO GIỜ ném.

tên Những chức năng thường cũng công nhận:

  • rõ ràng *()
  • sạch *()
  • Chấm dứt *()
  • Phá hủy *()
  • phát hành *()
  • Detach *()
  • Miễn phí *()
  • Xóa *()
  • ~ Destructor()
  • ...

Lý do mà đứng đằng sau này là:

  • có phải ít nhất 1 chức năng cho mỗi tài nguyên mà đảm bảo rằng tài nguyên cụ thể sẽ bị xóa
  • (đệ quy) nếu bạn xây dựng clean- lên chức năng và bạn phát hành nhiều tài nguyên sau đó chỉ sử dụng các chức năng mà đảm bảo rằng các tài nguyên này sẽ được phát hành theo cách ngoại lệ an toàn
  • lập trình viên sử dụng yo mã ur phải có cách để làm sạch-up tài nguyên
  • nếu bạn xuất chức năng dọn dẹp bên ngoài thư viện thì đừng tuyên truyền ngoại lệ (vì người sử dụng thư viện sẽ không biết nếu tài nguyên được giải phóng)

Và tôi có thể thử sử dụng RAII pattern. Nhưng ngay cả trong trường hợp này, các quy tắc trên sẽ được sử dụng.

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