2015-02-21 44 views
9

Tôi đã xem qua đoạn mã sau vào VS2008ngoại lệ lớp học với một char * constructor

if (!CreateProcess(NULL, 
        const_cast<LPWSTR>(ss.str().c_str()), 
        NULL, 
        NULL, 
        FALSE, 
        CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS, 
        NULL, 
        NULL, 
        &si, 
        &pi)) 
{ 
    throw std::exception("Unable to format Device"); 
} 

Bây giờ tôi porting mã để mingw gcc và tôi nhận được lỗi

error: no matching function for call to 'std::exception::exception(const char [23])' 

tra các vấn đề tôi nhận thấy rằng Visual Studio có một ngoại lệ tập tin mà không có một lớp học ngoại lệ và không có trong char *. Một số định nghĩa trông giống như thế này

__CLR_OR_THIS_CALL exception(); 
    __CLR_OR_THIS_CALL exception(const char *const&); 
    __CLR_OR_THIS_CALL exception(const char *const&, int); 
    __CLR_OR_THIS_CALL exception(const exception&); 
    exception& __CLR_OR_THIS_CALL operator=(const exception&); 
    virtual __CLR_OR_THIS_CALL ~exception(); 
    virtual const char * __CLR_OR_THIS_CALL what() const; 

Câu hỏi của tôi là làm cách nào để tránh sự cố xây dựng này trên mingw gcc? Tôi có nên tạo một lớp mới kế thừa từ std :: runtime_error và ném thay vào đó không?

+1

'std :: exception :: exception (const char *)' không phải là một tiêu chuẩn C++, thay vì một MS cụ thể implation http://en.cppreference.com/w/cpp/error/exception/exception –

Trả lời

33

Ý kiến ​​đóng một vai trò ở đây. Vấn đề là std::exception không có một hàm tạo có tham số chuỗi; đây là phần mở rộng MSVC. Tôi thấy hai cách để đi về nó:

  1. Không vượt qua một đối số chuỗi
  2. Không sử dụng std::exception

Trường hợp đầu tiên là đơn giản; chỉ cần sử dụng

throw std::exception(); 

Hạn chế là bạn không nhận được thông báo lỗi mô tả.

Nếu thông báo lỗi là quan trọng, sử dụng trực tiếp std::exception không phải là một tùy chọn. Trong trường hợp này, bạn có thể sử dụng một trong hai std::logic_error hoặc std::runtime_error, mà kế thừa std::exception và làm có nhà thầu tham gia một đối số chuỗi, vì vậy

throw std::runtime_error("Unable to format Device"); 

đã có thể giải quyết vấn đề. Các điều khoản catch bắt được số std::exception cũng sẽ bắt được số std::runtime_error. Tuy nhiên, có một vấn đề tiềm ẩn: catch các mệnh đề bắt giữ std::runtime_error sẽ không bắt được std::exception nhưng sẽ bắt được điều này.

Điều này có vẻ giống như một trường hợp góc và hoàn toàn có thể là nó không phải là vấn đề đối với bạn. Tuy nhiên, nếu có khả năng dọc theo ngăn xếp cuộc gọi có mệnh đề catch bắt giữ std::runtime_error nhưng không nên bắt ngoại lệ được ném bởi mã này, bạn có thể lấy được lớp ngoại lệ của riêng mình từ std::exception thực hiện đối số chuỗi. Bởi vì lớp học mới, nó sẽ không bị bắt bởi các mệnh đề catch hiện tại. Ví dụ:

class descriptive_exception : public std::exception { 
public: 
    descriptive_exception(std::string const &message) : msg_(message) { } 
    virtual char const *what() const noexcept { return msg_.c_str(); } 

private: 
    std::string msg_; 
} 

Và sau đó

throw descriptive_exception("Unable to format Device"); 

này được cho là không phải là rất xinh đẹp, và nó không chắc rằng nó là cần thiết, vì vậy giải pháp có thể xảy ra hơn là sử dụng std::runtime_error hoặc std::logic_error (hoặc một lớp học bắt nguồn từ một trong số họ).

Cho dù std::logic_error hoặc std::runtime_error phù hợp hơn không phải là rất rõ ràng; trong trường hợp này, tôi có thể đi với std::runtime_error vì lỗi này dường như không thể đoán trước được về mặt lý thuyết, nhưng cho rằng std::domain_errorstd::future_error xuất phát từ std::logic_error, nó sẽ không hoàn toàn nằm ngoài phân cấp đó. Đây là, tôi nghĩ, một vấn đề của ý kiến.

+0

Ồ, nắm bắt tốt. Đó là tất nhiên một lỗi đánh máy/suy nghĩ, bây giờ cố định. Cảm ơn. – Wintermute

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