流状态和c++的异常处理
出来混迟早是要还的系列(误)。
在学习OpenGL的时候,遇到了一些语言上的障碍(可以读懂,但是不知道具体用法),因此补了一下相关知识。
源代码如下:
std::ifstream vShaderFile; vShaderFile.exceptions(std::ifstream::failbit|std::ifstream::badbit); try { //...这里没有throw语句 } catch(std::ifstream::failure e) { std::cout<<"ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ"<<std::endl; }
先从简单的讲起,也就是try......catch......语句。
我们知道,对于一些异常(exception) c++自己不会处理,当运行程序遇到异常的时候也只会崩溃(crash),因此我们需要手动去捕获异常(当然这建立在你知道哪个代码块可能会出现异常的情况),手动捕获异常就需要这个try......catch......语句。
它们的分工是这样的:try负责检测语句块,catch负责去捕获这个异常,这就好比catch告诉try,你去检测一下你那边的语句块有没有异常,有的话告诉我,我来搞定,没有的话就别来烦我。。。另外值得一提的是,在try语句块中,发生异常的语句之后的语句都不会被执行到,只会直接跳转到catch语句。
还有需要说明的就是throw了,程序语句中的错误必须显式地被抛出,try语句才能检测到,再然后进一步被catch捕获。
因此形成了throw......try......catch体系。
但是很奇怪的是,我们发现上面的语句块里面并没有出现throw,这是为什么呢?
原因出现在更上面的ios::exceptions函数中。下面开始讲exceptions函数。
查找c++ reference中的ios::exceptions函数,给出来的定义是这样的
std::ios::exceptions get (1) iostate exceptions() const; set (2) void exceptions (iostate except); Get/set exceptions mask The first form (1) returns the current exception mask for the stream. The second form (2) sets a new exception mask for the stream and
clears the stream's error state flags (as if member clear() was called).
根据定义,我们可以知道重载一的返回值是当前流的异常掩码( exceptions mask )状态。
重载二对当前流设置一个新的状态掩码,并且清除流的错误状态标志(类似于调用了clear()函数)。当流本身的状态与当前的状态掩码一致的时候就会抛出异常(这就是为什么try语句中没有throw语句却还能正常抛出错误的原因了)。值得注意的是,默认的状态掩码是goodbit,此时流出错的话并不会主动抛出异常。
还有需要补充的就是rdstate()函数和(重载一) exceptions()函数之间的区别了。
我们知道这两个函数的返回值是iostate的值,iostate有四种情况:badbit, failbit,eofbit, goodbit。十进制值分别是4 2 1 0,因此这两个函数的返回值就看这四个状态标记位(iostate)的情况。我们知道exceptions()函数返回当前流设置的异常掩码(exceptions mask)状态,而rdstate()返回当前流本身的状态。
以上。
给出几个参考博客:
[1]C++ I/O库流状态标志位 (这里要注意他的failbit badbit goodbit eofbit的值是错误的,我写的才是对的)
[3]ios::exceptions - C++ Reference