切片std :: out_of_range to std ::异常在Visual Studio vs G 中

Slicing std::out_of_range to std::exception in Visual Studio vs g++

本文关键字:std Studio Visual vs to out of range 切片 异常      更新时间:2023-10-16

我注意到了以下行为(未参考),但是我找不到信息,如果我事先知道,我将允许我预测它。<<<<<<<<<<

与最小示例

#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 exceptionnstd::exception,第二次打印d.what() = Out of range exceptionnOut of range exception

原则上,当std::out_of_range被值捕获并转换为std::exception类型时,可能会切片。这意味着我期望在打印其what()时从std::out_of_range对象获得与对象相同的行为。

问题:我不知道该解释的部分是两个编译器的不同行为。这是因为这种切片是C 标准化中未定义的行为,还是这两个编译器中的一个不符合它?

额外的观察:我只是注意到,在此链接中,没有提及std::exception类具有输入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 what()"返回实现 - defined-defined字符串",因此MSVC可以自由这样做。

要打印类型,请将其添加到您的捕获块中:

std :: cout&lt;&lt;" e.what()="&lt;&lt;e.what()&lt;&lt;"实际类型="&lt;&lt;typeid( e).name()&lt;&lt;std :: endl;

相关文章: