[英]Slicing std::out_of_range to std::exception in Visual Studio vs g++
我偶然注意到了以下行為(錯過了通過引用捕捉),但我找不到信息,如果我事先知道的話,可以讓我預測它。
用最小的例子
#include <iostream>
#include <stdexcept>
int main()
{
try
{
// Added this and the next line to check that the exception
// created has already the what() set to the input string.
std::out_of_range d("Out of range exception");
std::cout << "d.what() = " << d.what() << std::endl;
throw d;
}
catch (std::exception e) // Captured by value
{
std::cout << e.what() << std::endl;
}
}
如果我用g++ -std=c++17
和 Visual C++ 編譯它,我會得到不同的行為。 第一個它打印d.what() = Out of range exception\\nstd::exception
,而第二個它打印d.what() = Out of range exception\\nOut of range exception
。
原則上,當std::out_of_range
被值捕獲並轉換為std::exception
類型時,可能會進行切片。 這意味着在打印其what()
時,我可能不會獲得與來自std::out_of_range
對象的對象相同的行為。
問題:我不知道如何解釋的部分是兩個編譯器的行為不同。 這是因為這種切片在 C++ 標准化中是未定義的行為,還是這兩個編譯器之一不符合它?
額外的觀察:我只是注意到在此鏈接中沒有提到類std::exception
具有輸入const char* const &
的構造const char* const &
,而在Microsoft 網站中它們包含它。 我偶然的例子表明他們確實以不同的方式實現了這些類。 我的問題仍然是他們是否被允許(如果此行為未定義)或者其中一個不遵守以及哪一個不遵守。
對象仍在切片中; 您可以使用typeid( e ).name()
打印出實際類型,它顯示為std::exception
。 如您所見,MSVC 實現what()
以返回指向在std::exception
構造時設置的字符串的指針,因此當out_of_range
異常被切回基本異常時它不會丟失。
根據https://en.cppreference.com/w/cpp/error/exception/exception , what() “返回一個實現定義的字符串”,所以 MSVC 可以自由地這樣做。
要打印類型,請將其添加到您的 catch 塊中:
std::cout << "e.what() = " << e.what() << " 實際類型 = " << typeid( e).name() << std::endl;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.