C++:通过引用抛出派生类在捕获基类时不起作用

use*_*875 11 c++ try-catch throw

我想在基类中抛出自己的异常Exception.有一个虚拟方法print将被子类覆盖.我只捕获类型Exception&并使用print来获取特定错误.问题是,一旦我抛出一个子类的引用,它就像它是基类一样被捕获.

这是一个例子:

#include <iostream>
using namespace std;

class Exception
{
    public:
        virtual void print()
        {
            cout << "Exception" << endl;
        }
};

class IllegalArgumentException : public Exception
{
    public:
        virtual void print()
        {
            cout << "IllegalArgumentException" << endl;
        }
};

int main(int argc, char **argv)
{
    try
    {
        IllegalArgumentException i;
        Exception& ref = i;

        cout << "ref.print: ";
        ref.print();

        throw ref;
    }
    catch(Exception& e)
    {
        cout << "catched: ";
        e.print();
    }
}
Run Code Online (Sandbox Code Playgroud)

这个例子的输出是:

ref.print: IllegalArgumentException
catched: Exception
Run Code Online (Sandbox Code Playgroud)

使用引用应该导致使用print派生类的方法.在try块内部,引用确实使用它.为什么捕获的Exception&行为不像是IllegalArgumentException,我怎么能得到这种行为?

以下代码似乎做了它应该做的事情:

try
{
    IllegalArgumentException i;
    Exception* pointer = &i;

    throw pointer;
}
catch(Exception* e)
{
    cout << "pointer catched: ";
    e->print();
}
Run Code Online (Sandbox Code Playgroud)

但是指针在try块的范围之外是否可能无效?这样做会有风险,如果我在堆上分配内存来解决这个问题,我有责任在catch块中删除它也不是很好.那你怎么解决这个问题呢?

ild*_*arn 6

throw隐式复制,因此切片.引用C++ 11,§15.1/ 3:

界外球表达初始化临时对象,叫做异常对象,其中所述类型的通过去除任何顶层确定cv修饰符从静态式抛的操作数的,由"的阵列调节型T或"功能"返回T"to"指针分别指向T"或"指向函数返回的指针T.临时值是一个左值,用于初始化匹配处理程序中指定的变量.如果异常对象的类型是不完整类型或指向不完整类型的指针(可能是cv-qualified),void则程序格式不正确.除了这些限制和15.3中提到的类型匹配限制之外,操作数throw被完全视为调用中的函数参数或return语句的操作数.

我已经看到了一些解决这个问题的代码库,它通过向异常而不是对象直接投掷指针,但我个人只是想重新考虑你的"需要"来做到这一点.

  • 您只需添加一个非成员模板:`template <typename ExceptionType> ExceptionType&addLine(ExceptionType&e,int line){e.addline(line); 返回e; 然后将`宏定义为`#define THROW_EXCEPTION(e)throw addLine(e,__LINE __)`. (4认同)