1、 C+教程 第一部分 预备知识 第 1 章程序文件 C+源程序分为两类文件。一类文件用于保存程序的声明,称为头文件。另一类文件用于保存程序的实现,称为源文件。头文件以“.h ”为后缀,源文件通常以“.cpp ”为后缀(也有一些系统以“.cc”或“.cxx”为后缀)。 C+编译器在扫描到一条函数调用语句时首先应当知道该函数的原型或定义,函数原型一般都放在头文件中,函数定义则放在源文件中,当源文件用#include 包含一个头文件的时候,编译预处理器用头文件的内容取代#include 伪指令。这就是说,头文件的所有内容最终都会被合并到某一个或某几个源文件中。 1.1 头文件的包含 #include
2、 有两种方式来指定文件:尖括号和双引号。 以尖括号指定文件,如下所示: #include 用尖括号来指定文件时,预处理器是以特定的方式来寻找文件,一般用来包含开发环境提供的库头文件,它指示编译预处理器在开发环境设定的搜索路径中查找所需的头文件。这种设置寻找路径的机制随机器、操作系统、C+实现的不同而不同。 以双引号指定文件,如下所示: #include “local.h” 用双引号时一般用来包含自己编写的头文件,它通常是从当前工作目录开始寻找,如果文件没有找到,再到开发环境设定的路径中去查找。 包含 iostream 头文件,要用如下语句: #include 预处理器会找到 iostream
3、头文件(通常在”include”子目录下)并把它插入头文件所在的位置。 1.2 标准 C+ include 语句格式 随着 C+的不断演化,不同的编译器厂商选用了不同的文件扩展名。而且,不同的操作系统对文件名有不同的限制,特别是对文件名长度限制。结果引起了对源代码的可移植性的限制。为了消除这些差别,标准使用的格式允许文件名长度可以大于众所周知的 8 个字符,去除了扩展名。例如,代替老式的包含 iostream.h 的语句 #include 现在可以写成: #include 新的包含格式和老的效果是不一样的:使用.h 的文件是老的、非模板化的版本,而没有.h的文件是新的模板化的版本。 1.3 名
4、字空间 在 C 语言中,当程序达到一定规模以后,会遇到的一个问题是我们“用完了”函数名称和标识符。当然并非我们真正用完了所有的函数名和标识符,而是简单的想出一个新名称就不太容易了。更重要的是,当程序达到一定的规模之后,通常分成许多块,每一块由不同的人或小组来构造和连接。由于所有的函数名和标识符都在同一个程序里,这就要求所有的开发人员都必须非常小心,不要碰巧使用了相同的函数名和标识符,导致冲突。 标准的 C+有预防这种冲突的机制: namespace 关键字。库或程序中的每一个 C+定义集被封装在一个名字空间中,如果其他的定义中有相同的名字,但它们不在同一个名字空间就不会产生冲突。 可以用一个关
5、键字来声明“我要使用这个名字空间中的声明和定义”。这个关键字是“using ”。所有的标准 C+库都封装在一个名字空间中,即 “std” (代表 standard). using namespace std; 这意味着打开 std 名字空间,使它的所有名字都可用。有了这条语句,就不用担心特殊的库组件是在一个名字空间中,因为在使用 using 指令的地方,它使名字空间在整个文件中都是可用的。 名字空间和前面所述包含头文件的方法之间存在着相互关系。新的头文件的包含命令已标准化了,老的包含方式里,名字空间不是语言的一部分。所以,对已存在的代码要提供向后兼容,如果给出 #include 它相当于 #i
6、nclude using namespace std; 第 2 章、简单的 C+程序的例子 下面给出几个简单的 C+程序的例子 2.1 hello world 程序 /Saying Hello with c+ #include /stream declarations using namespace std; void main() cout using namespace std; void main() int number; cout number; cout #include #include using namespace std; void main() ifstream in(“
7、FillString.cpp“); string s, line; while(getline(in, line) s += line + “n“; cout #include using namespace std; void main() vector v; for(int i = 0; i using namespace std; class rectangle / 矩形类 public: int m_nlength; int m_nwidth; int m_ncgrith; int m_nsarea; void m_Set(int x, int y); void m_Girth();
8、/求周长 void m_Area(); /求面积 void m_Display(); / 显示周长和面积 ; void rectangle:m_Set(int x, int y) m_nlength = x; m_nwidth = y; void rectangle:m_Girth() m_ncgrith = 2*(m_nlength + m_nwidth); void rectangle:m_Area() m_nsarea = m_nlength * m_nwidth ; void rectangle:m_Display() cout using namespace std; class H
9、uman public: Human() m_nNumber = -1 ; void Speak() coutSpeak(); pObj-Add(); / pObj-Run(); /错误,外界不能访问类的保护成员 / pObj-Eat(); /错误,外界不能访问类的私有成员 例 5 第 5 章 初始化与清除 初始化就是在对象创建时使用初始值直接填充对象的内存单元,因此不会有数据类型转换等中间过程,也就不会产生临时对象;而赋值则是在对象创建好后任何时候都可以调用的而且可以多次调用的函数,由于它调用的是“= ”运算符,因此可能产生临时对象。 编译器无法预期一个程序在执行过程中会在何时创建一些什么对
10、象,而只能根据当时的上下文要求来创建。对象的初始化最好能够通过运行时执行一个函数来完成,而且是在对象创建的同时,这个函数就是构造函数。同样,对象在完成其使命的时候能够通过一个函数来销毁,这就是析构函数。 把对象的初始化工作放在构造函数中,把清除工作放在析构函数中。当创建对象时,编译器自动调用构造函数。当对象消亡时,析构函数被编译器自动调用。因此就不必担心忘记对象的初始化和清楚工作了。 构造函数、析构函数与类同名,析构函数加前缀“ ”以示区别。 构造函数与析构函数的另一个特别之处就是没有返回类型,这与返回值类型为 void 的函数不同。析构函数不能带参数。 /Constructors class
11、 Tree int height; public: Tree(int initialHeight); /Constructor Tree(); /Destructor void grow(int years); void printsize(); ; Tree:Tree(int initialHeight) height = initialHeight; Tree:Tree() cout using namespace std; class String public: char* m_data; String(const char *str); String(void); ; String:
12、String(const char *str) if(str=NULL) m_data = new char1; *m_data = 0; else int length = strlen(str); m_data = new charlength+1; strcpy(m_data, str); String:String(void) delete m_data; void main() String str(“Hello Visul C+!“); cout using namespace std; class CCounter int m_int_result; float m_float_
13、result; public: CCounter(); CCounter(); void sum(int *iarray, int element_count); void sum(float *farray, int element_count); ; CCounter:CCounter() m_int_result = 0; m_float_result = 0.0; void CCounter:sum(int *iarray, int element_count) for(int i = 0; i using namespace std; class time private: int
14、m_hours; int m_minutes; int m_seconds; public: time(); time(int x); time(int x, int y); time(int x, int y, int z); void m_display(); /显示时间 ; time:time() m_hours =0; m_minutes = 0; m_seconds = 0 ; time:time(int x) m_hours = x; m_minutes = 0; m_seconds = 0 ; time:time(int x, int y) m_hours = x; m_minu
15、tes = y; m_seconds = 0 ; time:time( int x, int y, int z) m_hours = x; m_minutes = y; m_seconds = z; void time:m_display() cout #include using namespace std; class point int i,j, k; public: point(): i(0) ,j(0), k(0) point (int ii , int jj , int kk) : i(ii ) , j(jj), k(kk) ; void print (const string i
16、nt y; int const int int x = 0; int void main() cout #include using namespace std; ofstream out(“HowMany.out“); class HowMany string name; /object identifier static int objectCount; public: HowMany(const string HowMany(); HowMany(const HowMany void print(const string ; HowMany:HowMany(const string pr
17、int(“HowMany()“); HowMany:HowMany() -objectCount; print(“HowMany()“); HowMany:HowMany(const HowMany +objectCount; print(“HowMany(const HowMany void HowMany:print(const string class Byte unsigned char b; public: Byte(unsigned char bb = 0) : b(bb) const Byte class Tree int height; public: Tree (int treeheight) : height(treeheight) Tree() cout print(); delete t;