2016-03-29 13 views
6

http://ideone.com/UtVzxwHãy thử cú pháp bắt constructor

struct base 
{ 
    base() { throw std::exception(); } 
}; 

struct derived : public base 
{ 
    derived() try : base() { } 

    catch (std::exception& e) 
    { 
     std::cout << "exception handled" << std::endl; 
    } 
}; 

int main() 
{ 
    derived a; // My app crashes. 
    return 0; 
} 

Shoun't ứng dụng ghi của tôi "ngoại lệ xử lý" và tiếp tục chạy?

Giải pháp duy nhất tôi tìm thấy là bao quanh việc xây dựng "a" trong khối thử/nắm bắt. Nhưng nếu tôi làm điều đó, điểm của việc thử/bắt trong constructor ở vị trí đầu tiên là gì? Tôi đoán có lẽ nó sử dụng là để làm sạch các biến thành viên có thể đã được phân bổ? kể từ khi destructor không được gọi?

Các công trình sau đây, nhưng xử lý ngoại lệ 2 lần.

struct base 
{ 
    base() { throw std::exception(); } 
}; 

struct derived : public base 
{ 
    derived() try : base() { } 

    catch(std::exception& e) 
    { 
     std::cout << "exception 1" << std::endl; 
    } 
}; 

int main() 
{ 
    // This works fine. 
    try { 
     derived a; 
    } 
    catch(std::exception& e) 
    { 
     std::cout << "exception 2" << std::endl; 
    } 
    return 0; 
} 

Tôi chỉ cố gắng để tự hỏi mình tại sao tôi không nên chỉ đơn giản né tránh các cú pháp try/catch cho các nhà xây dựng và viết những dòng này:

struct base 
{ 
    base() { throw std::exception(); } 
}; 

struct derived : public base 
{ 
    derived() : base() { } 
}; 

int main() 
{ 
    // This works fine. 
    try { 
     derived a; 
    } 
    catch(std::exception& e) 
    { 
     std::cout << "exception handled" << std::endl; 
    } 
    return 0; 
} 

Trả lời

7

chức năng-try-block trong hàm tạo không ngăn ngoại lệ bị ném. Dưới đây là một đoạn trích từ C++ dự thảo tiêu chuẩn N4140, [except.handle]:

14 Nếu một tuyên bố trở lại xuất hiện trong một handler của chức năng-thử-block của một nhà xây dựng, chương trình là vô hình thành.

15 Ngoại lệ hiện được xử lý được trả về nếu điều khiển đến cuối trình xử lý chức năng-try-block của hàm tạo hoặc hàm hủy. Nếu không, ...

Lý do cho điều này là nếu lớp cơ sở hoặc bất kỳ thành viên nào tạo ra ngoại lệ, thì việc xây dựng toàn bộ đối tượng không thành công và không có cách nào để khắc phục, vì vậy ngoại lệ phải bị ném.

Có một GOTW về vấn đề này, và bottomline là

xử lý Constructor chức năng-thử-block chỉ có một mục đích - để dịch một ngoại lệ. (Và có thể để đăng nhập hoặc một số tác dụng phụ khác.) Chúng không hữu ích cho bất kỳ mục đích nào khác.

Vì vậy, có, mẫu mã cuối cùng của bạn hoàn toàn ổn.

+0

Vì vậy, giả sử bạn là google có chính sách không sử dụng ngoại lệ và bạn đã tìm thấy thư viện thú vị, nhưng lớp bạn muốn kế thừa từ các lần ném (chỉ trong hàm tạo, không ở bất kỳ nơi nào khác). Nếu bạn kế thừa từ nó, mọi người sử dụng lớp dẫn xuất phải sử dụng try/catch everytime. Bạn sẽ làm gì trong trường hợp đó? Có vẻ như câu trả lời duy nhất là: sử dụng một thư viện khác, chỉ do constructor ... – James

+0

@ Phantom hoặc không kế thừa từ nó, làm cho một con trỏ đến nó một thành viên và khởi tạo nó trong cơ thể constructor. Nhưng tôi tin rằng trong google họ sẽ không cho phép bạn sử dụng thư viện đó. –

3

Việc đóng gói một try/catch xung quanh constructor của lớp cha cho phép bạn bẫy các ngoại lệ được ném vào hàm tạo của lớp cha; tuy nhiên, ngoại lệ sẽ tự động bị thu hồi khi khối catch kết thúc và ngoại lệ tiếp tục lan truyền.

Sau khi tất cả, lớp cha không được xây dựng. Nó ném một ngoại lệ. Vì vậy, bạn không thể thực sự tiếp tục theo cách vui vẻ của bạn, trong constructor của lớp con, và sau đó kết thúc với một lớp con được xây dựng, nhưng với một lớp cha không được xây dựng. Điều đó không có ý nghĩa gì cả.

Từ http://en.cppreference.com/w/cpp/language/function-try-block:

Mục đích chính của chức năng-thử-khối là để đăng nhập hoặc sửa đổi, và sau đó rethrow các ngoại lệ ném khỏi danh sách khởi tạo thành viên trong một constructor. Chúng hiếm khi được sử dụng với các bộ hủy hoặc với các hàm thông thường.

Đây thực sự là giá trị gia tăng chính của khối thử chức năng: một nơi thuận tiện để ghi "hey, chức năng này đã ném ngoại lệ", bao gồm toàn bộ chức năng, một nơi duy nhất để đăng nhập loại này nhưng không ảnh hưởng đến việc xử lý ngoại lệ thông thường.

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