2017-01-12 20 views
6

Tôi vừa tạo cấu trúc phân cấp ngoại lệ và muốn khối catch của tôi hiển thị thông báo về ngoại lệ có nguồn gốc. tôi có 5 trường hợp ngoại lệ như thế này:Thừa nhận ngoại lệ trong C++

class ImagetypeException : public TGAException { 
public: 
const char* what() const throw(); 
}; 


const char* ImagetypeException::what() const throw() { 
    return "Der Bildtyp ist nicht \"RGB unkomprimiert\"."; 
} 

Tất cả đều có nguồn gốc từ TGAException, mà có nguồn gốc từ std :: ngoại lệ.

class TGAException : public std::exception { 
public: 
    virtual const char* what() const throw(); 
}; 

const char* TGAException::what() const throw() { 
    return "Beim Einlesen oder Verarbeiten der TGA-Datei ist ein unerwarteter Fehler aufgetreten!"; 
} 

Vì vậy, tôi rõ ràng muốn ném những mã này vào một thời điểm nào đó trong mã của mình và nghĩ rằng có thể là một ý tưởng hay, để giảm thiểu số lượng khối catch tôi cần.

catch (TGAException e) { 
     cout << e.what() << endl; 
    } 

Nếu tôi làm như vậy, thông báo sẽ được in, là từ TGAException, nhưng tôi muốn nó hiển thị thông điệp có nguồn gốc cụ thể hơn. Vì vậy, tôi cần làm gì để thực hiện điều này theo cách tôi muốn?

+4

Bắt bằng tham chiếu, như trong 'catch (TGAException & e)'. Khi bạn nắm bắt được giá trị, bạn [cắt nó] (https://en.wikipedia.org/wiki/Object_slicing) –

+1

tốt hơn, bắt bằng tham chiếu const vì bạn không có ý định thay đổi đối tượng ngoại lệ. @IgorTandetnik bạn nên làm điều này một câu trả lời (hoặc tôi sẽ nhưng tôi không cố gắng để ăn cắp đại diện) –

+1

Bạn đang làm * Object Slicing *, cho đến khi bạn bắt bằng cách tham chiếu. –

Trả lời

9

Khi bạn bắt như thế này:

catch (TGAException e) { 
    cout << e.what() << endl; 
} 

Trình biên dịch tạo một bản sao của các ngoại lệ ban đầu và gán nó vào e. Nó sử dụng hàm tạo bản sao TGAException để ngoại lệ nhìn thấy bên trong khối catch không phải là một ImagetypeException, nó là một TGAException. Hiện tượng này được gọi là đối tượng cắt.

Nếu bạn bắt nó theo cách này:

catch (const TGAException & e) { 
    cout << e.what() << endl; 
} 

Không sao chép là cần thiết và nó sẽ làm việc theo cách bạn mong đợi nó.

Nguyên tắc chung: Luôn bắt ngoại lệ theo tham chiếu và hầu như luôn luôn bắt chúng bằng tham chiếu const.

+0

cảm ơn! rất hữu ích và nhanh chóng trả lời :) nhưng một câu hỏi noob ở nơi đầu tiên -_- ' – Awesome36

+1

Không. Một câu hỏi hay. Bạn sẽ ngạc nhiên về việc có bao nhiêu lập trình viên C++ đã trải qua việc cắt đối tượng (lưu ý: nó có thể xảy ra trên các lời gọi phương thức khi các tham số và giá trị trả lại được truyền theo giá trị, hoặc thậm chí các bài tập khi đích không phải là một con trỏ hay tham chiếu.) –