2015-01-13 17 views
48

Tôi không chắc liệu đây có phải là vấn đề với trình biên dịch hay không nếu tôi làm sai điều gì đó. Tôi đang sử dụng trình biên dịch Visual Studio 2013.Constructor là một khối thử chức năng - Ngoại lệ hủy bỏ chương trình

Tôi có một lớp mà tôi cần để có được số lượng đáng kể tài nguyên trong danh sách khởi tạo hàm dựng của tôi, hầu hết trong số đó có thể ném một ngoại lệ. Tôi bọc danh sách initializer thành viên trong một khối thử chức năng và bắt được ngoại lệ ở đó. Nhưng chương trình của tôi vẫn hủy bỏ mặc dù điều khoản bắt không tái ném ngoại lệ. Tôi không được phép đăng mã thực tế. Vì vậy, tôi đã sao chép vấn đề với mã demo tương đương này. Ai đó có thể giúp tôi giải quyết vấn đề này không?

#include <iostream> 
using namespace std; 
class A{ 
public: 
    A() try : i{ 0 }{ throw 5; } 
    catch (...){ cout << "Exception" << endl; } 
private: 
    int i; 
}; 


int main(){ 
    A obj; 
} 

Khi thực thi mã này, tôi nhận được cảnh báo cửa sổ "hủy bỏ() đã được gọi". Vì vậy, tôi đoán hệ thống đang xử lý điều này như là một ngoại lệ không bị bắt và gọi chấm dứt().

Mặt khác, nếu tôi bọc cấu trúc của đối tượng trong chính() trong khối try-catch thì ngoại lệ sẽ bị bắt đúng và chương trình kết thúc bình thường.

Ai đó có thể vui lòng cho tôi biết nếu tôi đang làm điều gì sai ở đây?

+4

nhìn vào http://www.gotw.ca/gotw/066.htm cho một cuộc thảo luận về vấn đề này –

+0

Cảm ơn bạn rất nhiều Jan Herrmann. Nó rõ ràng làm cho rất nhiều ý nghĩa cho các tiêu chuẩn để nói rằng nếu một ngoại lệ không được rethrown hoặc nếu một esception mới không được ném từ chức năng thử khối của constructor sau đó nó sẽ được tự động rethrown ở phần cuối của catch khối. Điều này làm cho cảm giác hoàn hảo ngay bây giờ. Có lẽ như đề nghị thành ngữ pimpl là những gì tôi nên bắt đầu sử dụng. Cảm ơn rất nhiều lần nữa – Madhusudhan

+20

Điểm bổ sung cho * “Tôi không được phép đăng mã thực tế. Vì vậy, tôi đã sao chép vấn đề với mã demo tương đương này. ”* Bạn đã thực hiện một [MCVE] rất tốt (https://stackoverflow.com/help/mcve). – 5gon12eder

Trả lời

30

Có một gotw liên quan

http://gotw.ca/gotw/066.htm

Về cơ bản, ngay cả nếu bạn không vứt trong khối catch của bạn, ngoại trừ sẽ tự động được rethrown

Nếu cơ thể xử lý chứa tuyên bố " ném đi; " sau đó khối catch rõ ràng sẽ trả lại bất kỳ ngoại lệ nào A :: A() hoặc B :: B() đã phát ra . Điều ít rõ ràng hơn, nhưng được nêu rõ trong tiêu chuẩn, là nếu khối catch không ném (hoặc trả lại ngoại lệ ban đầu hoặc ném một cái gì đó mới) và điều khiển đến cuối khối bắt của một hàm tạo hoặc hủy , sau đó ngoại lệ gốc tự động được sửa lại.

+0

Trang đó thực sự tuyệt vời. Không biết cú pháp hàm-try-block tồn tại trước câu hỏi này; đã học được rất nhiều từ liên kết đó! Đặc biệt, có sự tương tự tuyệt vời: "Nếu xây dựng bất kỳ cơ sở hoặc thành viên nào thất bại, toàn bộ đối tượng * phải * thất bại ... không có cách nào cho con người [sinh ra] nếu bất kỳ nội tạng quan trọng nào chưa bao giờ được hình thành". – OJFord

+0

toàn bộ trang web gotw là một mỏ vàng cho bất kỳ nhà phát triển C++ nào! Cùng với trang web của Bjarne, parashift, cppreference và cplusplus –

+0

Tôi đã khám phá ra chỉ trong 48 phút kể từ khi tôi bình luận ở trên! Một sự xấu hổ gần đây nhất là 1/1/08. – OJFord

22

Đây là hành vi bình thường theo the cppreference.com documentation for function-try blocks: một cái gọi là chức năng-thử-block trên một constructor hoặc Destructor phải ném từ catch-khoản của mình hoặc nếu không có một rethrow ngầm sau khi bắt-khoản.

Điều này có ý nghĩa hoàn hảo: đối tượng A chưa được xây dựng đúng cách và do đó không ở trạng thái phù hợp để sử dụng: nó phải ném một ngoại lệ. Bạn phải đảm bảo rằng việc xây dựng thành công tại nơi mà đối tượng được xây dựng, tức là trong trường hợp của ví dụ của bạn trong main().

+4

Upvoting vì câu trả lời này có một câu trả lời dễ đọc hơn so với tiêu chuẩn được trích dẫn. Đối với OP: vấn đề của bạn là một hoặc nhiều thành viên của bạn đang ở trạng thái không bị cản trở (vì bạn không biết xây dựng thành viên nào bị ném, bạn không biết thành viên nào đã được xây dựng hoàn chỉnh). Vì vậy, lớp học của bạn không được xây dựng hoàn chỉnh. Có nó rethrow đảm bảo rằng bạn không thể sử dụng dụ này. Các thành viên đã được xây dựng hoàn toàn sẽ bị hủy một cách thích hợp. –

9

Ngoại lệ không thể bị bắt gặp trong hàm tạo function-try-block.

n3376 15,2/15

Ngoại lệ hiện xử lý được rethrown nếu kiểm soát đạt đến cuối của một handler của hàm-thử-block của một nhà xây dựng hoặc destructor.

Bạn nên bắt nó ở nơi tạo đối tượng.

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