《STL标准程序库》笔记1
来源:互联网 发布:中国报告大厅数据库 编辑:程序博客网 时间:2024/05/02 01:33
5.7
C++异常处理
class Error
void f()
{
try
{
...throw Error();
}catch( const Error e )
{
......
}
void f() throw(bad_alloc); //f只能抛出bad_alloc异常
void f() throw(); //f不抛出任何异常
关键字explicit
class Stack {
explicit Stack( int size ); //create stack with initial size
...
}
在这里,explicit非常重要,如果没有explicit,那么这个这个类将有能力将int自动转换为Stack。一旦这种情况发生,你甚至可以给Stack指派一个整数值而不会引起任何问题:
Stack s;
...
s = 40; //将会创建一个新的40个空间的Stack给s
自动类型转换动作会把40转换为有40个元素的Stack,并指派给s,这几乎肯定不是我们所要的结果。如果我们加上explicit,上述赋值动作就会导致编译错误。
新的类型转换操作
1.static_cast
将一个值以合逻辑的方式转换。这可看作是【利用原值重建一个临时物件,并在设立初值时使用类型转换】。唯有当上述的类型黄钻更换有所定义,整个转换才会成功。所谓有所定义,可以是语言内建规则,也可以是自定义的装换动作。例如:
float x;
...
cout<< static_cast<int>(x); //print x as int
....
f( static_cast<string>("Hello")); //call f() for string instead of char*
2.dynamic_cast
将类型向下转换为其实际类型。这是唯一在执行期进行检验的转换动作。你可以用它来检验某个类型,例如:
class Car;
class Cabriolet : public Car {
...
};
class Limousine : public Car {
...
};
void f(Car *cp)
{
Cabriolet *p = dynamic_cast<Cabriolet*>(cp);
if( p==NULL ) {
//did nor refer to an object of type Cabriolet
...
}
}
dynamic_cast失败时抛出一个bad_case异常。一般应尽量避免这种写法。
3.const_case
设定或去除类型的常数性(constness),亦可去除volatile修饰,除此之外不允许任何转换。
4.reinterpret_cast
。。。使用此转换带来不可移植性。
注意:这些操作符都只接受一个参数。看一下例子:
static_cast<Fraction>(15,100)
在这个例子中你得不到你想要的结果。它只用一个数值100,将15和100转换为分数的正确做法是Fraction(15,100);
常数静态成员(Constent Static Menbers)的初始化
我们能够在class中对定义常数静态成员直接赋予初值。初始化后,这个常数便可用于class中,例如:
class MyClass {
static const int num = 100;
int elems[num];
....
};
注意:你还必须为class之中定义的常数静态成员,定义一个空间:
const int MyClass::num;
main()的定义
正确而可移植的main()的唯一写法。根据C++标准规格,只有两种main()是可移植的:
int main()
{}
和
int main( int argc, char* argv[] )
{}
这个argv(命令参数列)也可定义为char**。
返回类型必须为int。你可以使用return语句来结束main(),但不必一定如此。这一点和C不同,换句话说,C++在main()的尾端定义了一个隐含的:
return 0;
这意味着如果你不采用return离开main(),实际上就表示成功退出(传回任何一个非零值都代表某种失败)。
标准异常类别
语言本身的异常
此类异常用以支撑某些语言特性,所以,从某种角度来说它们不是标准程序库的一部分,而是核心语言的一部分。如果一下操作失败,就会抛出这一类异常。
l 全局运算符new操作失败,会抛出bad_alloc异常(nothrow版本除外)。由于这个异常可能於任何时间在任何较复杂的程序中发生,所以可以说是最重要的一个异常。
l 执行期间,当一个动态类型转换动作失败时,dynamic_cast会抛出bad_cast异常。
l 执行期类型辨别过程中,如果交给typeid的参数为0或空指针,typeid操作符会抛出bad_typeid异常。
l 如果发生非预期的异常,bad_exception异常会接手处理,方式如下:当函数抛出异常规格以外的异常,bad_exception就会唤起unexpected()。例如:
class E1;
class E2; //not derived from E1
void f() throw(E1) //throws only exceptions of type E1
{
throw E1(); //throws exception of type E1
throw E2(); //calls unexpected(),which calls terminate()
}
f()内抛出类型E2的异常,这种动作违反了异常规格(exception specification)的设定,于是唤起unexpected(),后者通常会唤起terminate()中止程序。
然而如果你在你的异常规格列出bad_exception,那么unexpected()总是会重新抛出(rethrows)bad_exception异常。
class E1;
class E2; // not derived from E1
void f() throw( E1, std::bad_exception )
{
throw E1(); // throws exception of type E1
throw E2(); // calls unexpected(), which throws bad_exception
}
因此,如果异常规格罗列了bad_exception,那么任何未列于规格的异常,都将在函数unexpected()中被bad_exception取代。
(你可以修改unexpected()的具体操作。然而只要定义有异常规格,函数就绝不会抛出规格以外的异常)
C++标准程序库异常总是衍生自logic_error。理论而言,我们能够透过一些手段,在程序中避免逻辑错误——例如对函数参数进行额外测试等等。所谓逻辑错误包括未被逻辑前提或违反class的不变性。C++标准程序库提供一下逻辑错误类型:
l invalid_argument表示无效参数,例如将bitset(array of bits)以char而非'0'或'1'进行初始化。
l length_error指出某个行为可能超越了最大极限,例如对某个字符串附加太多字符。
l out_of_range指出参数值不在预期范围内,例如在array的群集(collection)或字符串(string)中采用一个错误索引。
l domain_error指出专业领域范畴内的错误。
此外,标准程序库的I/O部分提供了一个名为ios_base::failure的特殊异常。当资源串流(data stream)由于错误或由于到达尾端而发生状态改变时,就可能抛出这个异常。
程序作用域(scope of a program)之外发生的异常
衍生自runtime_error的异常,用来指出不在程序范围内,且不容易回避的事件。C++标准程序库指针对执行期错误提供了一下三个classes:
l range_error指出内部计算时发生区间错误(range error)。
l overflow_error指出算术运算发生上溢位(overflow)。
l underflow_error指出算术运算发生下溢位(underflow)。
标准程序库所抛出的异常
C++标准程序库自身可能抛出range_error、out_of_range和invalid_argument异常。也可能间接抛出任何异常。尤其是bad_alloc异常。
异常类型的头文件
exception和bad_exception定义于<exception>
bad_alloc定义于<new>
bad_cast和bad_typeid定义于<typeinfo>
ios_base::failure定义于<ios>
其他异常类型都定义于<stdexcept>
异常类型(Exception Classes)的成员
为了在catch子句中处理异常,你必须采用异常所提供的介面。所有标准异常的介面只含一个成员函数:what(),用以获取附加信息。它传回一个以null结束的字符串:
namespace std {
class exception {
public:
virtual const char* what() const throw();
...
}
}
被传回的字符串,期内容由实现者定义,它很大程度决定了帮助级别和信息的详细度。注意:该字符串可能以null结尾的“multibyte”字符串。
抛出标准异常
只需要一个string参数,它将成为被what()传回的描述字符串。例如:
namespace std {
class logic_error : public exception {
public:
explicit logic_error(const string& whatString);
};
}
提供这种功能的标准异常有:logic_error及其衍生类、runtime_error及其衍生类、ios_base::failure。你不能抛出exception,也不能抛出任何用以语言核心性质的异常。
想要抛出一个标准异常,只需要生成一个描述异常的字符串,并将它初始化,交给异常物件:
std:string s;
...
throw std::out_of_range(s);
由于char*可被隐式转换为string,所以你可以直接使用字符串字面常数:
throw std::out_of_range("out_of_range (somewhere, somehow)" );
从标准异常类(Exception Classes)中派生新类
由于what()是个虚函数,所以可以自己实现what():
namespace MyLib {
class MyProblem : public std::exception {
public:
...
virtual const char* what() const throw() { // what() function
...
}
};
void f() {
...
// create an exception object and throw it
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)
(源自:百度百科)
提供了类型化的内存分配以及对象的分配和撤销。
allocator类将对象分配和对象构造分开。当allocator对象分配内存的时候,它会分配适当大小并排列成保存给定类型对象的空间。
- 《STL标准程序库》笔记1
- 《STL标准程序库》笔记2
- 《STL标准程序库》笔记3
- 《STL标准程序库》笔记4
- 《STL标准程序库》笔记5
- 《C++标准程序库STL》笔记
- 《STL标准程序库》笔记6-vector
- 《STL标准程序库》笔记7-deque
- 《STL标准程序库》笔记8-List
- C++标准程序库STL
- 《C++标准程序库》学习笔记(一)初识STL
- C++标准程序库 学习笔记 第九章 STL算法
- C++ STL标准程序库初探
- C++标准程序库笔记(1)
- C++STL标准程序库开发指南(1)
- C++标准程序库 学习笔记 第五章 STL(标准模板库概述)
- C++标准程序库学习笔记
- C++标准程序库笔记---迭代器
- session 验证
- session 验证
- 3D和IMAX 3D带你体验加勒比的惊涛怪浪
- C语言实现顺序表
- 裸机系列——supervivi烧写
- 《STL标准程序库》笔记1
- 心爱的嗲王
- VS2008 PRO 、WDK 和DDKWizard搭建驱动开发环境
- 集合1
- 办公平台主要的目的是什么?
- 共享内存
- 介绍一篇关于session的好文章,写的很详细
- extern "C"----实现c cpp文件的混合编程
- 哲学家就餐问题