2013-06-16 23 views
8

Tôi đang học xử lý ngoại lệ trong C++ và gặp sự cố. Đây là mã:lỗi: không thể dynamic_cast ... (mục tiêu không phải là con trỏ hoặc tham chiếu)

#include<iostream> 
#include<exception> 

using namespace std; 

class A 
{ 
public: 
    virtual void f(void){} 
}; 

class AA:public A 
{ 
public: 
    void aa(void){}; 

}; 

int main(void) 
{ 

    A a; 
    try 
    { 
     dynamic_cast<AA>(a).aa(); 
    } 
    catch(exception ex) 
    { 
     cout<<"["<<ex.what()<<"]"<<endl; 
    } 
    return 0; 
} 

Vì vậy, tôi nghĩ thử bắt đầu sẽ cho phép hàm thực thi và hiển thị cho tôi nội dung ngoại lệ, nhưng trình biên dịch của tôi không biên dịch nó. Tôi đang sử dụng codeblock với GNU GCC. Xin hãy giúp tôi và chỉ cho tôi những gì tôi cần làm để có được mã chạy như tôi dự định. cảm ơn rất nhiều.

+0

Bạn đang gặp phải lỗi trình biên dịch. Điều quan trọng là bạn phải chia sẻ lỗi đó trong câu hỏi của mình để bạn có thể tìm hiểu cách đọc và hiểu chúng. –

+0

chắc chắn. "không thể dynamic_cast 'a' (thuộc loại 'lớp A') để nhập 'lớp AA' (đích không phải là con trỏ hoặc tham chiếu) – focusHard

+1

Vấn đề chính ở đây là' dynamic_cast' hoạt động trên con trỏ hoặc kiểu tham chiếu. Không phải là con trỏ hay kiểu tham chiếu – Chad

Trả lời

3

Bạn đang gặp lỗi trình biên dịch vì dynamic_cast của bạn không có trên con trỏ hoặc tham chiếu.
Thay đổi nó để:

dynamic_cast<AA&>(a).aa(); 

... và bạn sẽ có được ngoại lệ thích hợp ném.

Về phía lưu ý: trình biên dịch thông minh như g ++ sẽ cảnh báo cũng như:
cảnh báo: dynamic_cast vào một đối tượng (ở đây a) không bao giờ có thể thành công.

Vì vậy, tốt hơn nên hạn chế mã như vậy để giải trí xung quanh. Trong mã chất lượng sản xuất, dynamic_cast chỉ nên được thực hiện trên con trỏ/tham chiếu.

18

dynamic_cast chỉ có thể truyền tới giá trị hoặc tham chiếu con trỏ, chính xác là lỗi mà bạn đang nói.

Từ $ 5.2.7/1 của tiêu chuẩn C++.

The result of the expression dynamic_cast< T >(v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or “pointer to cv void.”

Để ném một ngoại lệ khi đối tượng không thể chuyển đổi bạn cần truyền sang tham chiếu. Thay đổi nó như sau:

dynamic_cast<AA&>(a).aa(); 
//   ^^^ cast to reference. 

Như Johnsyweb chỉ ra dynamic_cast sẽ luôn ném std::bad_cast khi chuyển đổi thất bại. Mặc dù std::bad_cast có nguồn gốc từ std::exception nó luôn luôn là một ý tưởng tốt để sử dụng ngoại lệ phù hợp nhất với điều kiện thất bại dự kiến. Điều này ngăn chặn vô tình giải thích các lỗi khác như một diễn viên không thành công.

Để áp dụng điều này cho ví dụ của bạn, nó có thể trông giống như mã bên dưới.

#include <iostream> 
#include <typeinfo> // std::bad_cast 

class A 
{ 
public: 
    virtual void f(void){} 
}; 

class AA:public A 
{ 
public: 
    void aa(void){}; 
}; 

int main(void) 
{ 
    A a; 

    try 
    { 
     dynamic_cast<AA&>(a).aa(); 
    } 
    catch(const std::bad_cast& ex) 
    { 
     std::cout << "["<<ex.what()<<"]" << std::endl; 
    } 
    return 0; 
} 

[Lưu ý rằng, những việc như using namespace std; không được khuyến khích vì có thể gây xung đột với số nhận dạng trong không gian tên chung. Tôi đã gỡ bỏ nó trong ví dụ trên]

+0

cảm ơn, lời giải thích của bạn rất rõ ràng – focusHard

+0

sau sửa đổi mã của tôi thành , chương trình kết quả đầu ra [std :: exception] .làm cách nào để có được std :: bad_cast? bạn có thể vui lòng minh họa không? Ví dụ mã? thanks – focusHard

+0

@focusHard, đặt một 'catch (std :: bad_cast & e)' trên khối 'catch()' hiện tại và '#include '. – iammilind

5

Vấn đề của bạn không phải là với xử lý ngoại lệ, nhưng với dàn diễn viên năng động bạn:.

'AA' is not a reference or pointer 

dynamic_cast an toàn chuyển đổi con trỏ và tài liệu tham khảo để class es và không phải trường hợp.

Vì vậy, bạn có thể làm:

dynamic_cast<AA&>(a).aa(); 

... mà sẽ luôn thất bại và ném một ngoại lệ std::bad_cast.

Bạn nên nắm bắt những loại nhất cụ thể của exception mà bạn đang mong đợi và vì the recommended way to catch is by reference, bạn nên thích: đọc

catch (std::bad_cast const& ex) 

Hơn nữa:dynamic_cast conversion trên cppreference.com.

+0

Tôi đã cố gắng nắm bắt (std :: bad_cast const & cũ) như bạn đề xuất nhưng nhận được một số thông báo lỗi. "dự kiến ​​loại-specifier", "dự kiến ​​unqualified-id trước khi 'const'" – focusHard

+1

'std :: bad_cast' được định nghĩa trong tiêu đề' '. Bạn sẽ cần phải '# include' này. – Johnsyweb

0

Tôi chỉ xử lý cùng một lỗi, nhưng trong trường hợp của tôi, tôi đã đi từ một con trỏ đến một con trỏ, vì vậy các câu trả lời khác ở đây không áp dụng. Thông báo lỗi của tôi hơi khác, tuy nhiên: error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type).

Nguyên nhân gốc rễ trong trường hợp của tôi đơn giản và phức tạp hơn nhiều.

Lưu ý việc thêm để hoàn thành loại ở cuối. Điều này khiến tôi nhớ rằng tôi không bao gồm tệp tiêu đề cho lớp mà tôi đang sử dụng. Nó không phải là một biểu tượng không rõ vì A* được chuyển tiếp tuyên bố với class A; trong tệp tiêu đề, khiến nó tồn tại nhưng không hoàn thành, do đó lỗi.

Giải pháp trong trường hợp của tôi là bao gồm tệp tiêu đề cho lớp tôi đã truyền tới.

Đây không phải là vấn đề của người hỏi câu hỏi ở trên, nhưng có thể thấy trường hợp của tôi có thể tạo ra cùng một loại lỗi.