Từ 1 tới 3 trên tổng số 3 kết quả

Đề tài: type của exception object trong lệnh throw

  1. #1
    Ngày gia nhập
    04 2011
    Bài viết
    2

    Mặc định type của exception object trong lệnh throw

    C++ Code:
    1. #include <iostream>
    2. #include <exception>
    3.  
    4. class Base //: public std::exception
    5. {
    6. };
    7.  
    8. class Derived : public Base
    9. {
    10. };
    11.  
    12. void throwit( Base & e )
    13. {
    14.     std::cout << "Kieu cua e la " << typeid(e).name() << '\n';
    15.   throw e;
    16. }
    17.  
    18.  
    19. int main()
    20. {
    21.   Derived e;
    22.  
    23.   try
    24.   {
    25.     throwit( e );
    26.   }
    27.   catch( Derived& )
    28.   {
    29.     std::cout << "Caught derived\n";
    30.   }
    31.   catch ( Base&  )
    32.   {
    33.     std::cout << "Caught base\n";
    34.   }
    35.  
    36.   return 0;
    37. }

    1) Khi em để nguyên, hay bỏ kí hiệu comment // để khai báo
    Code:
    : public std::exception
    thì cả hai trường hợp đều cho kết quả là Caught base
    2) Nhưng, nếu có khai báo
    Code:
    class Base : public std::exception
    (trong phần comment)thì kiểu của e là class Derived
    còn nếu bỏ đi thì kiểu của e là class Base.

    Mong các anh/chị giải thích cho em 2 hiện tượng trên. Em có đọc một số tài liệu mà còn mơ hồ quá.

  2. #2
    Ngày gia nhập
    07 2011
    Bài viết
    160

    C++ có cơ chế RTTI (runtime type information) giúp có thể nhận biết được kiểu của dữ liệu lúc chạy (runtime). Compiler thì chỉ biết kiểu lúc dịch chương trình (compile-time)

    Vấn đề 1. Tại sao kết quả luôn luôn là Caught base
    Vì đối số của hàm throwitBase& e. Vì vậy kiểu của e lúc compile-time là Base&. Throw chỉ làm việc trên kiểu compile-time, thực chất nó sẽ phải tạo ra 1 bản sao của e, và kiểu của bản sao đó đương nhiên là Base. Tại sao lại phải tạo bản sao (copy/clone) ? Vì e có thể là 1 đối tượng nằm trên stack, và khi catch thì có thể e sẽ không còn giá trị. Nên khi throw, compiler phải copy về vùng nhớ an toàn.

    Vấn đề 2. std::cout << "Kieu cua e la " << typeid(e).name() << '\n';
    Bạn cần hiểu cơ chế RTTI của C++ (typeid sử dụng RTTI khi đối số là con trỏ hoặc tham chiếu). RTTI dựa vào virtual table để nhận biết kiểu run-time của đối tượng. Do đó đối tượng phải có ít nhất 1 method là virtual thì typeid mới trả về kiểu runtime được. Nếu đối tượng hoàn toàn không có virtual thì typeid sẽ trả về kiểu compile-time.
    Khi bạn kế thừa từ std::exception thì class Base của bạn sẽ có virtual table (do std::exception có virtual function what() và virtual destructor) nên typeid mới trả về đúng kiểu runtime được. Nếu không kế thừa từ std::exception, bạn có thể khai báo cho Base 1 virtual function bất kỳ hoặc virtual destructor cũng sẽ được kết quả tương tự

  3. #3
    Ngày gia nhập
    04 2011
    Bài viết
    2

    Anh giải thích rất chi tiết và dễ hiểu.
    Em đã thử và tìm hiểu thêm theo các keyword của anh thì đúng như vậy.
    Xin cảm ơn nhiều.

Các đề tài tương tự

  1. Báo lỗi Unable to cast object of type 'System.DBNull' to type khi restore database với sqlserver 2008 r2
    Gửi bởi b0yt4l3nt9z trong diễn đàn Thắc mắc lập trình ASP.NET
    Trả lời: 1
    Bài viết cuối: 26-10-2012, 06:18 PM
  2. Exception Lỗi: "The type initializer for 'PublicMethods' threw an exception."?
    Gửi bởi khatran trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 1
    Bài viết cuối: 29-02-2012, 06:42 PM
  3. Trả lời: 0
    Bài viết cuối: 18-08-2011, 05:37 PM
  4. Lỗi load modules trong C# (Báo lỗi the type initializer for threw '' an exception)
    Gửi bởi mrgatay trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 4
    Bài viết cuối: 11-08-2011, 11:36 AM
  5. MS SQL Lỗi unable to cast object of type ... to type ... sửa như thế nào?
    Gửi bởi Riku trong diễn đàn Thắc mắc Microsoft SQL Server & Microsoft Access
    Trả lời: 7
    Bài viết cuối: 31-12-2010, 11:34 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn