Vì không có finally
trong C++ you have to use the RAII mẫu thiết kế thay thế, nếu bạn muốn mã của mình là ngoại lệ an toàn. Một cách để làm điều này là bằng cách sử dụng các destructor của một lớp địa phương như thế này:Thay thế thích hợp cho thiếu 'cuối cùng' trong C++
void foo() {
struct Finally {
~Finally() { /* cleanup code */ }
} finalizer();
// ...code that might throw an exception...
}
Đây là một lợi thế lớn so với các giải pháp thẳng về phía trước, bởi vì bạn không cần phải viết mã dọn dẹp 2 lần:
try {
// ...code that might throw an exception...
// cleanup code (no exception)
} catch (...) {
// cleanup code (exception)
throw;
}
Một bất lợi lớn của giải pháp lớp địa phương là bạn không thể truy cập trực tiếp các biến cục bộ trong mã dọn dẹp của mình. Vì vậy, nó sẽ sưng lên mã của bạn rất nhiều nếu bạn cần truy cập vào chúng bất kể:
void foo() {
Task* task;
while (task = nextTask()) {
task->status = running;
struct Finally {
Task* task;
Finally(Task* task) : task(task) {}
~Finally() { task->status = idle; }
} finalizer(task);
// ...code that might throw an exception...
}
}
Vì vậy, câu hỏi của tôi là: Có một giải pháp kết hợp cả hai lợi thế? Vì vậy, bạn a) không phải viết mã trùng lặp và b) có thể truy cập các biến cục bộ trong mã dọn dẹp, như task
trong ví dụ cuối cùng, nhưng không có mã bloat như vậy.
Đó là Ugly. Bạn nên tạo một RunObject hoặc một cái gì đó !!! –
+1 để hỏi điều này bởi vì nó quá phổ biến để thấy những người không quen thuộc với 'RAII' nghĩ rằng' cuối cùng' là tốt ... –
"bạn không phải viết mã dọn dẹp 2 lần". Tại sao bạn lại viết mã hai lần, vì lý do nào? Đó là những chương trình con cho = P Trung lập về câu hỏi của RAII vs cuối cùng, nhưng viết mã hai lần là một cá trích đỏ: bạn có thể tạo ra một thói quen dọn dẹp, truyền nhiệm vụ cho nó và gọi nó ở hai nơi. Không cần sao chép mã. Trong ví dụ đơn giản của bạn, một cách hợp lý là một phần của destructor của nhiệm vụ. Nhưng nếu có một số lý do bạn muốn dọn dẹp trong foo, sau đó tạo ra một thói quen dọn dẹp cục bộ ở đó. – ToolmakerSteve