簡體   English   中英

在 Visual Studio 與 g++ 中將 std::out_of_range 切片為 std::exception

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM