Den*_*hie 7 c++ stl exception hierarchy
为什么C++标准会打扰发明std::exception类?他们的好处是什么?我的理由是:
try
{
throw std::string("boom");
}
catch (std::string str)
{
std::cout << str << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
工作良好.后来,如果我需要,我可以制作自己的轻量级"异常"类型.那我为什么要打扰std::exception?
Alo*_*ave 11
为什么C++标准会打扰发明
std::exception类?他们的好处是什么?
它提供了一个通用且一致的接口来处理标准库抛出的异常.标准库生成的所有异常都是从中继承的std::exception.
请注意,标准库api可以抛出许多不同类型的异常,举几个例子:
std::bad_allocstd::bad_caststd::bad_exceptionstd::bad_typeidstd::logic_errorstd::runtime_errorstd::bad_weak_ptr | C++11std::bad_function_call | C++11std::ios_base::failure | C++11std::bad_variant_access | C++17等等...
std::exception是所有这些异常的基类:

为所有这些异常提供基类,允许您使用公共异常处理程序处理多个异常.
如果我需要,我可以制作自己的轻量级"异常"类型.那我为什么要打扰std::exception?
如果您需要自定义异常类,请继续进行.但是std::exception让你的工作更容易,因为它已经提供了许多功能,这是一个很好的异常类应该具备的功能.它为您提供了易于从中获取并为您的类功能覆盖必要的功能(特别是std::exception::what()).
这为您提供了2个std::exception处理程序的优势,
图片提供:http://en.cppreference.com/w/cpp/error/exception
为什么C++标准需要发明std :: exception类?他们的好处是什么?
具有不同类型的异常允许您捕获特定类型的错误.从公共基础派生异常允许根据环境捕获更多通用或特定错误的粒度.
在C++中,现有的类型系统已经到位,因此当您可以在语言中显式创建所需类型的异常时,不需要标准化错误字符串.
std :: exception及其派生类的存在主要有两个原因:
标准库必须具有某种异常层次结构才能在特殊情况下抛出.总是抛出一个std :: string是不合适的,因为你没有干净的方法来定位特定类型的错误.
为库供应商提供可扩展的基于类的接口,以抛出最基本的错误类型并为用户提供共同的回退.您可能希望提供比简单的what()字符串更多的错误元数据,以便捕获错误的人可以更智能地从中恢复.
同时std :: exception作为一个共同的基础允许一般的catchall不那么包罗万象......如果用户只关心那个错误信息.
如果您所做的只是打印并退出,那么它并不重要,但您也可以使用std :: runtime_error继承自std :: exception以方便catch.
后来,如果我需要,我可以制作自己的轻量级"异常"类型.那么我为什么要打扰std :: exception呢?
如果从std :: runtime_error继承并使用自己的自定义错误类型,则可以追溯性地添加错误元数据,而无需重写catch块!相反,如果您更改了错误处理设计,那么您将被迫重写所有std :: string catch,因为您无法安全地从std :: string继承.这不是一个前瞻性的设计决定.
如果现在看起来不那么糟糕,想象一下,如果你的代码在多个项目中作为共享库共享,并且各种程序员都在使用它.迁移到新版本的库会变得很痛苦.
这甚至没有提到std :: string可以在复制,构造或访问字符时抛出自己的异常!
Boost的网站在异常处理和一流的施工人员一些很好的指导方针在这里.
我正在编写一些网络代码并使用第三方供应商的库.在用户输入的无效IP地址上,此库将引发从std :: runtime_error派生 的自定义异常nw :: invalid_ip.nw :: invalid_ip包含一个描述错误消息的what(),还包含提供的incorrect_ip()地址.
我还使用std :: vector来存储套接字,并且正在使用checked at()调用来安全地访问索引.我知道如果我在()上调用超出界限的值,则抛出std :: out_of_range.
我知道其他事情也可能被抛出,但我不知道如何处理它们,或者它们究竟是什么.
当我得到一个nw :: invalid_ip错误时,我弹出一个带有输入框的模态,用于填充无效ip地址的用户,这样他们就可以编辑它并再试一次.
对于std :: out_of_range问题,我通过对套接字运行完整性检查并修复已失去同步的向量/套接字关系来做出响应.
对于任何其他std :: exception问题,我使用错误日志终止程序.最后我有一个捕获(...)记录"未知错误!" 并终止.
仅仅抛出std :: string就很难做到这一点.
这是在不同情况下抛出的一些事情的基本示例,因此您可以使用捕获异常.
#include <vector>
#include <iostream>
#include <functional>
#include <stdexcept>
#include <bitset>
#include <string>
struct Base1 {
virtual ~Base1(){}
};
struct Base2 {
virtual ~Base2(){}
};
class Class1 : public Base1 {};
class Class2 : public Base2 {};
class CustomException : public std::runtime_error {
public:
explicit CustomException(const std::string& what_arg, int errorCode):
std::runtime_error(what_arg),
errorCode(errorCode){
}
int whatErrorCode() const {
return errorCode;
}
private:
int errorCode;
};
void tryWrap(typename std::function<void()> f){
try {
f();
} catch(CustomException &e) {
std::cout << "Custom Exception: " << e.what() << " Error Code: " << e.whatErrorCode() << std::endl;
} catch(std::out_of_range &e) {
std::cout << "Range exception: " << e.what() << std::endl;
} catch(std::bad_cast &e) {
std::cout << "Cast exception: " << e.what() << std::endl;
} catch(std::exception &e) {
std::cout << "General exception: " << e.what() << std::endl;
} catch(...) {
std::cout << "What just happened?" << std::endl;
}
}
int main(){
Class1 a;
Class2 b;
std::vector<Class2> values;
tryWrap([](){
throw CustomException("My exception with an additional error code!", 42);
});
tryWrap([&](){
values.at(10);
});
tryWrap([&](){
Class2 c = dynamic_cast<Class2&>(a);
});
tryWrap([&](){
values.push_back(dynamic_cast<Class2&>(a));
values.at(1);
});
tryWrap([](){
std::bitset<5> mybitset (std::string("01234"));
});
tryWrap([](){
throw 5;
});
}
Run Code Online (Sandbox Code Playgroud)
Custom Exception: My exception with an additional error code! Error Code: 42
Range exception: vector::_M_range_check
Cast exception: std::bad_cast
Cast exception: std::bad_cast
General exception: bitset::_M_copy_from_ptr
What just happened?
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1581 次 |
| 最近记录: |