2010-04-03 27 views
10

Với này mẫu mã:C++ Exceptions và thừa kế từ std :: ngoại lệ

#include <iostream> 
#include <stdexcept> 

class my_exception_t : std::exception 
{ 
public: 
    explicit my_exception_t() 
    { } 

    virtual const char* what() const throw() 
    { return "Hello, world!"; } 
}; 

int main() 
{ 
    try 
     { throw my_exception_t(); } 
    catch (const std::exception& error) 
     { std::cerr << "Exception: " << error.what() << std::endl; } 
    catch (...) 
     { std::cerr << "Exception: unknown" << std::endl; } 

    return 0; 
} 

tôi nhận được kết quả như sau:

Exception: unknown 

Tuy nhiên, chỉ đơn giản là làm cho thừa kế my_exception_t từ std::exceptionpublic, tôi nhận được sản lượng sau:

Exception: Hello, world! 

Ai đó có thể pl dễ dàng giải thích cho tôi tại sao loại thừa kế lại quan trọng trong trường hợp này? Điểm thưởng cho một tham chiếu trong tiêu chuẩn.

Trả lời

20

Khi bạn thừa kế riêng, bạn không thể chuyển đổi sang hoặc truy cập vào đó lớp cơ sở bên ngoài lớp học. Kể từ khi bạn yêu cầu một cái gì đó từ tiêu chuẩn:

§11.2/4:
Một lớp cơ sở được cho là có thể truy cập nếu một thành viên cộng đồng phát minh của lớp cơ sở có thể truy cập. Nếu một lớp cơ sở có thể truy cập được, người ta có thể chuyển đổi hoàn toàn một con trỏ thành một lớp dẫn xuất thành một con trỏ tới lớp cơ sở đó (4.10, 4.11).

Nói một cách đơn giản, với bất kỳ thứ gì bên ngoài lớp, bạn không bao giờ được kế thừa từ std::exception, vì nó là riêng tư. Ergo, nó sẽ không thể bị bắt trong mệnh đề std::exception&, vì không có chuyển đổi nào tồn tại.

+0

Được chấp nhận cho tham chiếu chuẩn; cảm ơn! – fbrereto

9

Ai đó có thể giải thích cho tôi lý do tại sao loại vấn đề kế thừa trong trường hợp này? Điểm thưởng cho tham chiếu trong tiêu chuẩn.

Loại thừa kế không quan trọng. Nó chỉ quan trọng là bạn có một chuyển đổi có thể truy cập có sẵn cho một trong các loại bắt. Nó chỉ xảy ra vì nó không phải là thừa kế công khai nên không có chuyển đổi có thể truy cập công cộng.


Giải thích:

Bạn có thể thấy hành vi tương tự ở đây:

class B 
{ 
}; 

class C1 : B 
{ 
}; 

class C2 : public B 
{ 
}; 

int main(int argc, char** argv) 
{ 
    B& b1 = C1();//Compiling error due to conversion exists but is inaccessible 
    B& b2 = C2();//OK 
    return 0; 
} 

Một ngoại lệ ném chỉ bắt bởi một khối catch nếu:

  1. Việc nắm bắt khối có loại đối sánh hoặc
  2. Khối catch là cho một loại có một chuyển đổi truy cập
  3. Khối catch là một catch (...)
+0

'my_exception_t' có nguồn gốc từ' std :: exception' trong cả hai trường hợp. – fbrereto

+0

@fbrereto: Cảm ơn bạn đã giải thích rõ, tôi đã giải thích trong câu trả lời của tôi, vui lòng đọc lại. –