C++中bad_alloc按值捕获时what虚函数多态生效原因问询
问题解答
核心结论
你理解的C++多态规则完全正确:按值捕获异常必然发生对象切片,虚函数的运行时多态只能通过基类指针或引用触发,你观察到的std::bad_alloc按值捕获时输出正确的what()结果,并非多态生效,而是标准库对std::exception的实现特性导致的。
具体原因拆解
- 标准库
std::exception的内部实现:主流编译器的STL(比如GNU libstdc++、MSVC STL)中,std::exception内部会存储一个指向异常描述字符串的指针,其自带的what()成员函数的逻辑就是直接返回这个内部指针。当你从std::bad_alloc对象切片拷贝构造std::exception对象时,这个描述字符串指针会被一起拷贝到基类对象中,因此哪怕对象已经被切片为纯基类实例,调用基类的what()也会返回原本std::bad_alloc设置的字符串"bad_alloc"。 - 自定义异常的差异:你自己实现的
MyException重写了虚函数what(),直接在派生类的what()中返回自定义的常量字符串,没有给基类std::exception的内部描述指针赋值。当对象切片发生后,捕获到的已经是纯基类std::exception实例,调用的就是基类默认的what(),自然会返回默认的"Unknown exception"。
补充验证
如果你的自定义异常在构造时调用基类的带参构造函数传入描述字符串,比如:
class MyException : public std::exception { public: MyException() : std::exception("My custom Exception") {} };
此时哪怕按值捕获,基类what()也会返回你设置的自定义字符串,表现和std::bad_alloc一致,但这依然不是多态,只是基类本身存储了字符串而已。
异常捕获最佳实践
永远用const引用捕获异常,也就是catch (const std::exception& e),既可以避免对象切片、保证多态正常生效,也能避免不必要的对象拷贝,同时不要抛出异常指针,容易出现内存泄漏问题。
内容的提问来源于stack exchange,提问作者ArunJose
相关产品推荐
相关产品推荐

