中国科大学继续教育学院 李艺 leeyi@ustc

42
Object-Oriented Programming in C++ 第第第 C++ 第第 中中中中中中中中中中中 中中 [email protected]

Upload: aitana

Post on 24-Jan-2016

162 views

Category:

Documents


10 download

DESCRIPTION

Object-Oriented Programming in C++ 第八章 C++ 工具. 中国科大学继续教育学院 李艺 [email protected]. 第一章 C++ 的初步知识 第二章 类和对象 第三章 再论类和对象 第四章 运算符重载 第五章 继承与派生 第六章 多态性与虚函数 第七章 输入输出流 第八章 C++ 工具 第九章 模板. 8.1 异常处理 8.2 命名空间 8.3 使用早期的函数库. 8.1 异常处理. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 中国科大学继续教育学院    李艺 leeyi@ustc

Object-Oriented

Programming

in C++

第八章 C++ 工具

中国科大学继续教育学院 李艺[email protected]

Page 2: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 2

第一章 C++ 的初步知识第二章 类和对象第三章 再论类和对象第四章 运算符重载第五章 继承与派生第六章 多态性与虚函数第七章 输入输出流第八章 C++ 工具第九章 模板

Page 3: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 3

8.1 异常处理8.2 命名空间8.3 使用早期的函数库

Page 4: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 4

8.1 异常处理概述:程序的错误有两种:一种是编译错误,即语法错误。

另一种是在运行时发生的异常 (exception) 。 异常处理机制只处理运行时的差错和其它例外情况,不包括编译错误。

处理异常的方法有:非结构化异常处理:用 exit (n) 或 return (n) 的运行期

错误处理机制,具有“一个入口,多个出口”的特点。 exit() 会清空流和关闭打开的文件。 abort() 却不会清空流,也不关闭打开的文件。

结构化的异常处理:按“警告—忽略”、“对话—补救”或安全退出等模式,使程序可以在对运行条件做出适当安排或改善后继续运行下去。

Page 5: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 5

8.1 异常处理 基本思想:

C++ 的异常处理的基本思想是将异常的检测与处理分离。 在一个函数体中检测到异常条件满足,但无法确定相应

的处理方法时,就引发一个异常,然后由函数的直接或间接调用者处理此异常。

C++ 的异常处理建立在三个关键字基础之上:try 、 catch 和 throw 。

Page 6: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 6

8.1 异常处理C++ 异常处理语句的一般形式try { //try 块内监视异常 if (条件) throw exception; // 由 throw 抛出异常 … ; // 其它语句

}catch( 类型 1 参数 1 ) { //catch 块内处理代码 }catch( 类型 2 参数 2 ) { … ; } ……catch( 类型 n 参数 n ) { … ; }

注意: C++ 通过 try 夺取运行期的环境控制权,即异常的引发是由程序员控制的,而不是由程序运行环境或计算机硬件控制的。任何要检测异常的语句或函数调用都必须在 try语句块中执行。异常由紧跟在 try块后的 catch语句来捕获并处理。

Page 7: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 7

8.1 异常处理#include<iostream.h>#include<math.h>float Div(float x,float y);void main( ){ try { float a=1.0,b; while (a>0.0) { cout << " 请输入被除数: "; cin >> a; cout << " 请输入除数: "; cin >> b;

cout<<"a/b="<<Div(a,b)<<endl; }

} catch (float) { cout<<"deviding is zero.\n\n"; } cout<<"that is ok.\n";}float Div(float x,float y){ if (fabs(y)<0.0001) throw y; return x/y;}

方框中的代码是没有

异常处理机制的代码

Page 8: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 8

8.1 异常处理说明

如果预料某段程序代码有可能发生异常,就将它放在 try

子句的化括号中。如果这段代码运行时真的遇到异常情况,其中的 throw 表达式就会抛出这个异常。

出现异常时, try 语句块提示编译器到哪里查找catch 块,没有紧跟 try 块的 catch 块是没有作用的。

当没有发生异常的时候,几乎没有和 try 块相关的运行时成本。查找匹配捕获处理异常的过程只在发生异常的情况下才会进行。

Page 9: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 9

8.1 异常处理catch 子句后的复合语句是异常处理程序。它捕获由

throw 表达式抛出的异常。异常类型说明部分指明该子句处理的异常的类型,

它与函数的形参是相似的。可以是某个类型的值,也可以是引用。

如果某个 catch 语句的参数类型与引发异常的信息数据类型相匹配,则执行该 catch 语句的异常处理(捕获异常),此时,由 throw 语句抛出的异常信息(值)传递给 catch 语句中的参数。

Page 10: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 10

8.1 异常处理try 语句块必须出现在前, catch 紧跟在后。 catch 之

后的圆括号中必须含有数据类型,捕获是利用数据类型匹配实现的。在 try{…} 和 catch(…){ …} 语句之间不得插入任何其它 C++ 语句。

如果程序内有多个异常处理模块,则当异常发生时,系统自动查找与该异常类型相匹配的 catch 模块,查找次序为 catch 出现的次序。需要注意的是 catch 处理程序的出现顺序很重要,因为在一个 try 块中,异常处理程序是按照它出现的顺序被检查的。

Page 11: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 11

8.1 异常处理引发异常的 throw 语句必须在 try 语句块内,或是由

try 语句块中直接或间接调用的函数体执行。 throw 语句的一般形式为: throw exception;

exception 表示一个异常值,它可以是任意类型的变量、对象或常量。

Page 12: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 12

8.1 异常处理#include<iostream.h>const double PI=3.1416;void invoke(int x){ try{

if(x==0) throw x+5; // 抛出 int 型的异常if(x==1) throw 'A'; // 抛出 cahr 型的异常if(x==2) throw "An apple"; // 抛出字符串型的异

常if(x==3) throw PI; // 抛出 double 型的异常

}catch(int i){ cout<<"catch a integer "<<i<<endl; } catch(char c){ cout<<"catch a char "<<c<<endl; } catch(char str[10]){ cout<<"catch a string "<<str<<endl; } catch(double d){ cout<<"catch a double "<<d<<endl; }

}

程序运行结果:catch a integer 5catch a char Acatch a string An applecatch a double 3.1416

void main(){ invoke(0); invoke(1); invoke(2); invoke(3);}

Page 13: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 13

8.1 异常处理异常的类型匹配规则

C++规定,当一个异常对象和 catch 子句参数类型符合下列条件时,匹配成功:如果 catch 子句参数类型就是异常对象的类型或其引用 如果 catch 子句参数类型就是异常对象的 public 基类如果 catch 子句参数类型为基类指针或引用,而异常对象为派生类指针或引用。

catch 子句参数类型为 void*, 异常对象为任何类型指针。catch 子句为 catch-all ,即 catch{…} 。

catch 处理程序按照其在 try 块后面的顺序依次为检测,一旦匹配,则后面的就不再检测。

Page 14: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 14

8.1 异常处理异常的匹配规则比函数重载的匹配规则更为严格 try { throw int(); }

catch (unsigned int) { …… }

抛出异常的类型是 int 型,然而 handler 却期待一个unsigned int 。异常处理机制不认为二者是能够匹配的类型;结果,抛出的异常没有被捕获。

Page 15: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 15

8.1 异常处理异常重抛 ( re-throw ) :

当 catch 捕获异常后,可能不能完全处理异常,在完成某些操作后,可以重新抛出该异常,把异常传递给上层函数的另一个catch 子句,由它进一步处理。重新抛出异常的表达式仍然为:throw; 被重新抛出的异常就是原来的异常对象。如:

void f( ) { try {throw 1;} catch (int e) { //do something; throw ; } }int main( ) { try { f(); } catch ( int e) {cout << “exception in main is ” << e;} return 0;}

Page 16: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 16

8.1 异常处理#include<iostream> #include <string>using namespace std;void myFunc( ){try { int a; cout<<"正在执行 myFunction 函数 \n"; string e=" 输入的数据超限 "; cout <<" 请输入一个小于 5 的自然数 :"; while (cin>>a) { if ((a<1)||(a>4)) throw e; else { cout<<" 输入的数据 "<<a<<" 合格 \n\n"; if (a==1) exit (0); else cout <<“ 请输入一个小于 5 的自然数 :"; } } }catch (string& e){ cout<<" 在 myFunc( ) 中捕到一个异常 "<<endl; throw e; }}

void main( ){ try{ myFunc( ); } catch (string& e) { cout<<e<<endl; }}

Page 17: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 17

8.1 异常处理重抛异常的 catch 子句应该把自己做过的工作告诉下

一个处理异常的 catch 子句,往往要对异常对象做一定修改,以表达某些信息。

因此 catch 子句中的异常声明必须被声明为引用,这样修改才能真正做在异常对象自身中,而不是拷贝中。

Page 18: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 18

8.1 异常处理 catch_all 子句

  通常异常发生后按栈展开( stack unwinding )退出,动态分配的非类对象资源是不会自动释放的,应该在对应的catch 子句中释放。因为我们不知道可能被抛出的全部异常,所以不是为每种可能的异常写一个 catch 子句来释放资源,而是使用通用形式的 catch 子句 catch_all ,格式为:

catch(...) { 代码 }

Page 19: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 19

8.1 异常处理catch_all 子句示例:void fun1( )

{ int *res;

  new res[100];// 定义一个资源对象   try{// 代码包括使用资源 res 和某些可能引起异常抛出的操

作 }

}

catch(...)

{ delete res[];//正常退出前释放资源对象 res;

  throw;// 重新抛出异常}

   catch_all 子句可以单独使用,也可以与其它 catch 子句联合使用。但必须放在相关 catch 子句表的最后。

Page 20: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 20

8.1 异常处理异常的限制

在异常处理中,由于捕获和抛出一个异常会影响到一个函数与其它函数的相互关系。因此, C++ 异常机制允许在函数定义后面增加一个抛出类型说明,以限制该函数可以抛出的异常类型。异常限制的一般格式如下:

返回值类型 函数名 (< 参数表 >) throw (< 异常类型列表 >)

{ …. }

 使用时应特别注意,经这样定义的函数 , 抛出的异常数据只能是异常类型列表中的一种。

Page 21: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 21

8.1 异常处理

如果一个函数抛出的异常没有在抛出类型列表中说明或者从所列数据类型之一派生,默认的异常处理过程就是调用名为 unexpected() 的函数,该函 数又调 用 terminate() 函 数 , 后 者依次再 调 用abort() 函 数 终 止 程 序 运 行 。 其 中 , 对unexpected() 和 terminate() 用户可以提供自己的函数定义。

Page 22: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 22

8.1 异常处理

例 12. 3 异常限制演示 (VC++6.0无此功能 )#include <iostream.h>void invoke(int test) throw(int, char){ if (test==0) throw test; if (test==1) throw 'a'; if (test==2) throw 123.23; }void f(int t){ try { invoke(t); } catch (int j) { cout<<"Caught an integer "<<j<<endl; } catch (char c) { cout<<"Caught a char: "<<c<<endl; } catch (double d) { cout<<"Caught a double "<<d<<endl; }}

void main( ){ f(0); f(1); f(2); cout<<"End"<<endl;}

执行结果如下:Caught an integer 0Caught a char: aAbnormal program terminate

Page 23: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 23

8.1 异常处理异常成组

将多个有某种关联的异常放在一组。这些异常通常属于某一个方面的异常。比如文件异常组。

在 C++ 异常处理中,有两种方式把多个异常成组。它们是:异常枚举成组和异常派生类成组。

Page 24: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 24

8.1 异常处理 ( 异常枚举成组 )

#include <iostream.h>enum errs{err0,err1,err2};void f(int test){ try { if(test==0) throw err0; if(test==1) throw err1; if(test==2) throw err2; } catch(errs er) { switch(er) { case err0: cout<<"Caught err0 exception\n"; break;

case err1: cout<<"Caught err1 exception\n"; break; case err2: cout<<"Caught err2 exception\n"; break; } }}void main( ){ f (2); f (1); f (0);}

Page 25: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 25

8.1 异常处理异常和派生类成组

 在 C++ 程序中,表示异常的类通常被组成为一个组( group )或者一个层次结构。对由栈类成员函数抛出的异常:

class popOnEmpty{...};class pushOnFull{...};

 可以定义一个称为 Excp 的基类,再从该基类派生出这两个异常类。

class Excp{...};class popOnEmpty:public Excp{...};class pushOnFull:public Excp{...};

Page 26: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 26

8.1 异常处理由基类 Excp来打印错误信息:

class Excp

{public:

void print (string msg) {cerr << msg << endl; }

};

这样的基类也可以作为其他异常类的基类:class Excp{...}; //所有异常类的基类class stackExcp:public Excp{...}; //栈异常类的基类class popOnEmpty:public stackExcp{...}; //栈空退栈异常class pushOnFull:public stackExcp{...}; //栈满压栈异常class mathExcp:public Excp{...}; // 数学库异常的基类class zeroOp:public mathExcp{...}; // 数学库零操作异常class divideByZero:public mathExcp{...}; // 数学库被零除异常

Page 27: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 27

8.1 异常处理这里被创建的异常类对象是 stackExcp 类类型,尽管 pse指向一

个实际类型为 pushOnFull 的对象,但那是一个临时对象,拷贝到异常对象的存贮区中时创建的却是 stackExcp 类的异常对象。所以该异常不能被pushOnFull 类型的 catch 子句处理。

在处理类类型异常时, catch 子句的排列顺序是非常重要的。当异常被组织成类层次结构时,类类型的异常可以被该类类型的公有基类的catch 子句捕获到。如 pushOnFull 类类型的异常可以由 stackExcp 或Excp 类类型异常所对应的 catch 子句处理。为了保证 pushOnFull 异常的处理由最合适的 catch 子句来处理,应有如下顺序:

catch (pushOnFull){...} // 处理 pushOnFull 异常catch (stackExcp){...} // 处理栈的其他异常catch (Excp){...} // 处理一般异常

派生类类型的 catch 子句必须先出现,以确保只有在没有其他catch 子句适用时,才会进入基类类型的 catch 子句。

Page 28: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 28

8.1 异常处理

异常派生类成组示例:对学生信息 ( 姓名、年龄、成绩 ) 进行输入,要求将输入不合理的数据抛出不用。

思路:先定义一个抽象类check;由它派生出三个派生类:nameCheck 、 ageCheck 和 scoreCheck ,来分别检查name 、 ade 、 score录入是否合理,如果不合理,则抛出不用。

长处:用派生类成组进行异常处理,其 catch 字句可以非常精练、易读。

#include<iostream>#include<string>using namespace std;class check{public: virtual void set()=0; virtual void showErr()=0; virtual void display()=0;protected: string name; int age; int score;}; // 检查抽象类结束

Page 29: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 29

8.1 异常处理class nameCheck:public check{public: void set() { cout<<" 请输入姓名: "; cin>>name; if (isNum(name)) throw this; } void showErr() { cout << "姓名输入错误! " << endl; } void display() { cout << "\n\n 学生姓名: "<<name<<endl; } private: bool isNum(string &s) { char num[] = "1234567890"; for (int i=0;i<10;i++) if (s.find(num[i])!=-1) return true; return false; }}; // 姓名输入检查类结束class ageCheck:public check{public: void set() { cout<<" 请输入年龄: "; cin>>age; if (age<0 || age>120) throw this; } void showErr() { cout << "年龄输入错误! " << endl; } void display() { cout << " 学生年龄: "<<age<<endl; }}; // 年龄检查类结束

class scoreCheck:public check{public: void set() { cout<<" 请输入成绩: "; cin>>score; if (score<0 || score>100) throw this; } void showErr() { cout << " 成绩输入错误! " << endl; } void display() { cout << " 学生成绩: "<<score<<endl; }}; // 成绩检查类结束int main(){ try { check *pt1,*pt2,*pt3;

pt1 = new nameCheck; pt1->set(); pt2 = new ageCheck;

pt2 -> set(); pt3 = new scoreCheck;

pt3 -> set();pt1->display();pt2->display();pt3->display();

} catch(check *chk) { chk->showErr(); } return 0;}

Page 30: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 30

8.1 异常处理类层次结构的异常同样可以重新抛出( rethrow ),

把一个异常传递给函数调用列表中,更上层的另一个 catch子句。形式仍为

throw;   虚函数是类层次结构中多态性的基本手段,异常类层次结

构中也可以定义虚拟函数。

Page 31: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 31

8.1 异常处理例 : 异常层次结构中的虚函数

#include <iostream.h>class Excp{ public: virtual void print( ) {cerr<<” 发生异常” <<endl;}};class stackExp:public Excp{ public: virtual void print( ) {cerr<<”栈发生异常” <<endl;}};class pushOnFull:public stackExcp{ public: virtual void print( ) {cerr<<”栈满 , 不能压栈” <<endl;}};

int main(){ try { // 抛出一个 pushOnFulll 异常 } catch(Excp&eObj) { eObj.print(); // 调用虚函数   pushOnFull::print() }}

Page 32: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 32

8.2 命名空间本课程的各章节的程序中,都用到了这样的语句:

using namespac std;

这就是命名空间 std 。为什么需要命名空间? C 语言定义了 3 个作用域,即文件域,

函数域和复合语句域。 C++又引入了类作用域。不同的作用域中可以用相同的变量名,互不干扰。但

是,如果是在不同的库文件 ( *.h ) 中,有相同的变量名和类名,而不巧又在被一个程序包含、主文件中又调用了该变量,定义了该类对象,于是引起矛盾冲突。

Page 33: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 33

8.2 命名空间什么是命名空间?为了解决这个问题, ANSI C++增加了命

名空间的概念。简单地说,就是 ANSI C++ 引入的,可以由用户命名的内存区域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。比如:

namespace nsl

{ int a;

double b;

}

其中:namespace 是定义命名空间的关键字;nsl 是用户指定的空间名。花括号内包含的 a,b ,是命名空间成员。

Page 34: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 34

8.2 命名空间注意 a 和 b 仍然是全局变量,仅仅把它们隐藏在

命名空间中,而程序中如果要使用变量 a 和 b ,必须加上空间名和域分辨符。如: nsl::a , nsl::b 等。这些名字称为被限定名。

C++ 中的命名空间和被限定名的关系,类似与操作系统中文件夹和其中文件的关系。

命名空间的作用:是建立一些互相分隔的作用域,把一些全局实体分割开来,以免产生名字冲突。命名空间中的被限定名可以是: 常量和变量 ( 可以带有初始化 ); 函数 ( 可以是定义或声明 ); 结构体或类; 模板或另一个命名空间 ( 意味着,命名空间可以嵌套 )

Page 35: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 35

8.2 命名空间使用命名空间解决名字冲突:我们举例说明如何解决冲突。

// header1.h#include <string>#include <cmath>using namespace std;namespace ns1 // 声明命名空间 ns1{ class student // 在 ns1 中声明学生类 {public: student (int n, string nam, int a) { num=n; name=nam; age=a; } void get_data( ); private: int num; string name; int age; }; void student::get_data() {cout<<num<<“ “<<name <<““<<age<<endl; double fun (double a, double b) { // 在 ns1 中定义 fun 函数 return sqrt(a+b); }}

// header2.h#include <string>#include <cmath>using namespace std;namespace ns2 // 声明命名空间 ns2{ class student // 在 ns1 中声明学生类 {public: student (int n, string nam, char s ) { num=n; name=nam; sex=s; } void get_data( ); private: int num; char name[20]; int age; }; void student::get_data() {cout<<num<<“ “<<name <<““<<sex<<endl; double fun (double a, double b) { // 在 ns1 中定义 fun 函数 return sqrt(a-b); }}

Page 36: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 36

8.2 命名空间 两个头文件中有相同名字的

类和函数,分别放在不同的命名空间中,避免冲突。

定义对象时,要使用:空间明 :: 类名 对象名 ( 参数表 )

的形式来定义对象。 定义好的对象不在命名空间

中,而在 main 函数的范围里,所以使用对象时,不能加空间的名字!

// main file#include <iostream>#include “header1.h”#include “header2.h”using namespace std;int main( ){ nsl::student stud1(101,”Wang”,18); stud1.get_data( ); // 不要写成ns1::stud1.get_data( ) cout<<ns1::fun(5,3)<<endl;

ns2::student stud2(102,”Li”,’f’); stud2.get_data( ); cout<<ns2::fun(5,3)<<endl;

return 0;}

Page 37: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 37

8.2 命名空间 使用命名空间的简化形式:如果在一个命名空间中定义了至少 10 个实体,

就需要至少使用 10次 using 命名空间名。能否简化呢?可以。C++ 提供 using namespace 语句来实现简化。其一般形式为: using namespace 命名空间名;

例如, using namespace ns1;

声明了在本作用域中要用到命名空间 ns1 中的成员,在使用该命名空间的任何成员时,都不必使用 ns1 空间名来限定。好象全局对象一样。如果紧接上面的声明,有如下语句:

student stud1(101, “Wang”,18);

则是指定义一个 ns1 空间中的 student 类对象。注意,这种简化方法只能是使用少量的命名空间,并且不至于

产生冲突的情况下,才能简化。如上一个示例中, ns1 两个 ns1 命名空间就不能简化,因为会引起冲突。

Page 38: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 38

8.2 命名空间无名的命名空间: C++允许使用没有名字的命名空间,如:

namespace

{ void fun( )

{ cout<<“OK!”<<endl; }

}

这种无名的名字空间在其他文件中无法引用,只能在本文件的作用域内有效。无名空间中的成员,如上面提到的函数 fun 的作用域是从定义位置开始到文件结束的范围。

Page 39: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 39

8.2 命名空间标准命名空间 std :为了解决 C++标准库中的标识符与程序

中的全局标识符之间,以及不同库之间的同名冲突,应该将不同库的标识符在不同的命名空间中定义。

标准 C++ 库的所有标识符都是在一个名为 std 命名空间中定义的。或者说,标准头文件 ( 如 stream) 中的函数、类、对象和类模板是在命名空间 std 中定义的。

这样,在程序中用到 C++标准库的被限定成员时,如: std::cout<<“OK.”<<endl;

在程序头一般要加上 using namespace std;每当用到 std 命名空间中的被限定成员时,就可省略

std:: 限定语。如: cout<<“OK.”<<endl;

Page 40: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 40

8.3 使用早期的函数库在 C 语言的发展过程中,产生了丰富的函数库。 C+

+ 可以使用这些函数库。要使用它们,就必须在程序中包含相关的头文件。

C++ 使用这些头文件有两种方法:用 C 语言的传统方法。头文件名包括后缀 .h ,如 stdio.h 、

math.h 等,由于 C 语言没有命名空间,头文件并不存放在命名空间中,因此在 C++ 程序文件中如果用到带 .h 后缀的头文件时,不必使用命名空间,只需要包含要用到的头文件名就行。如:

#include <math.h>

Page 41: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 41

8.3 使用早期的函数库用 C++ 的新方法: C++标准要求系统提供的头文件不包括

后缀 .h 。例如, iostream, string 。为了区别于 C 语言的头文件, C++头文件相应的文件名之前都加一字母 c 。例如, C 语言的 stdio.h 文件, C++ 中改名为 cstdio 。 C

语言中的 string.h 头文件, C++ 中改名为 cstring 。并且后者增加了很多内容,不是同一个文件。

此外,由于这些函数都是在命名空间 std 中声明的,因此在程序中要对命名空间 std 作声明。比如:

#include <cstdio>

#include <cmath>

using namespace std;

Page 42: 中国科大学继续教育学院    李艺 leeyi@ustc

C++ 8- 42

习题:本章习题请上网查阅教学网页:

http://staff.ustc.edu.cn/~leeyi