这篇文章上次修改于 2320 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

3. 一般概念

命名空间(namespace) std

namespace 可以用了解决命名冲突,具有扩展开放性,可以出现在任何源码文件中。c++标准库中的所有标识符都定义在一个名为std的namespace中。
使用标准库标识符,有三种选择
1 直接指定标识符,如std::ostream,

std::cout << std::hex << 3.4 << std::endl;

2 使用using declaration

using std::cout;
using std::endl;
于是之前的例子可以写成
cout << std::hex << 3.4 << endl;

3 使用using directive 如果对namespace std使用using directive 可以让std内定义的所有标识符都有效。

using namespace std;
之后可以写:
cout << hex << 3.5 << endl;

错误处理和异常处理

标准库有一部分支持具体的错误处理,如string class,检查所有可能发生的错误,并在错误发生时抛出异常。其他部分如STL和valarrays,几乎不检查逻辑错误,只会在执行期(runtime)发生错误才抛出异常。
标准异常类可以分为三组:

    1. 语言本身支持的异常
    1. C++标准库发出的异常
    1. 程序作用域(scope of a program)之外发出的异常

语言本身支持的异常:

  • 全局操作符new操作失败,抛出bad_alloc异常,该异常可以在任何时间任何较复杂的程序中发生。
  • 执行期间,当一个对reference的动态类型转换操作失败时,dynamic_cast会抛出bad_cast异常。
  • 执行期类型辨识(RTTI)过程中,如果交给typeid的参数为零或空指针,typeid操作符会抛出bad_typeid异常
  • 如果发生非预期的异常,bad_exception异常会接手处理,方式如下:当函数抛出异常规格(exception specification)以外的异常,bad_exceptio就会调用unexceptiond() 例子:

    class E1;
    class E2;
    void f() throw(E1)
    {
        throw E1();
        throw E2();
    }

    如果在异常规格中列出了bad_exception,那个unexpected()总是会重新抛出(rethrows)bad_exception异常

    class E1;
    class E2;
    void f() throw(E1, std::bad_exception)
    {
        throw E1();
        throw E2();
    }

    C++ 标准库发生的异常
    c++标准容器库异常总是派生自logic_error,从理论上讲,我们能够通过一些手段,在程序中避免逻辑错误。所谓逻辑错误包括未被逻辑前提或违背class不变性。

    • invalid_argument表示无效参数,例如将bitset以char而非‘0’或‘1’进行初始化。
    • length_error支出某个行为“可能超越了最大极限”,例如对某个字符串附加太多字符。
    • out_of_range指出参数值“不在预期范围内”,例如在诸如array的容器或字符串中采用一个错误索引。
    • domain_error指出专业领域范畴的错误

程序作用域之外发生的异常
派生自runtime_error的异常,用来指出“不在程序范围内,且不容易回避”的事件。

  • range_error指出内部计算时发生区间错误
  • ouverflow_error指出算术运算发生上溢位(overflow)
  • underflow_error指出算术运算发生下溢位(underflow)

异常类别的头文件

基础类别exception和bad_exception定义于<exception>。bad_alloc定义于<new>。 bad_cast 和bad_typeid 定义于<typeinfo>。ios_base::failure定义于<ios>。其他异常类型定义于<stdexcept>

异常类别的成员

为了在catch子句中处理异常,必须采用异常提供的接口,所有标准异常的接口只含有一个成员函数:what(),用来获取“类型本身以外的附加信息",返回一个null结束的字符串:

namespace std{
    class exception {
        public:
            virtual const char * what() const throw();
    }
}

抛出标准异常:
可以在自己的程序库或程序内部抛出某些标准异常。
logic_error定义如下:

namespace std{
    class logic_error: public exception {
        public :
            explicit logic_error (const string & whatString);
    }
}

throw std::out_of_range("out_of_range(somewhere , somehow)")

从标准异常类别中派生新类别

一种使用标准异常的情况,定义一个直接或间接派生自exception的特定异常类别。自己实现what();

namespace MyLib {
    class MyProblem :public std::exception {
        public:
        MyProblem () {
        }
     virtual const char* what() const throw() {
     
     }
    }
    ...
    void f() {
        ...
        throw MyProblem();
    }
}

另一种提供what的方式是派生自前面提到的标准异常

namespace MyLib {
    class MyRangeProblem : public std::out_of_range {
        public:
        MyRangeProblem (const string & whatString) :out_of_range (whatString) {
        }
    }
    void f() {
    throw MyRangeProblem("here is my special range problem");
    }
}

配置器(Allocators)

C++标准程序库在很多地方采用特殊对象来处理内存配置和寻址。这样的对象称为配置器(allocator)。
C++程序库中定义了一个缺省配置器(default allocator):

namespace std{
    template <class T>
    class allocator;
}