600 likes | 783 Views
第 2 章 C++ 初步知识. 主要内容. 2.1 C++ 发展历程和特点 2.2 简单的 C++ 程序 2.3 C++ 对 C 的扩充. 2.1 C++ 的产生和特点. 2.1.1 C++ 的产生 C++ 是美国贝尔实验室于 1980 年开发出来的一种过程性与面向对象性结合的程序设计语言。最初他把这种新的语言叫做“含类的 C”, 到 1983 年才取名为 C++ 。. 2.1.2 C++ 的特点 (1) C++ 保持与 C 兼容。 (2) 用 C++ 编写的程序可读性更好 , 代码结构更为合理 , 可直接地在程序中映射问题空间的结构。
E N D
主要内容 2.1 C++发展历程和特点 2.2 简单的C++程序 2.3 C++对C的扩充
2.1 C++的产生和特点 2.1.1 C++的产生 C++是美国贝尔实验室于1980年开发出来的一种过程性与面向对象性结合的程序设计语言。最初他把这种新的语言叫做“含类的C”,到1983年才取名为C++。
2.1.2 C++的特点 (1) C++保持与C兼容。 (2) 用C++编写的程序可读性更好,代码结构更为合理,可直接地在程序中映射问题空间的结构。 (3) 生成代码的质量高,运行效率仅比汇编语言代码段慢10%到20%。 (4) 从开发时间、费用到形成的软件的可重用性、可扩充性、可维护性和可靠性等方面有了很大的提高,使得大中型的程序开发项目变得容易的多。 (5) 支持面向对象的机制,可方便地构造出模拟现实问题的实体和操作。
2.2 C++程序的结构特性 2.2.1 一个简单的C++示例程序 例2.1 在屏幕上显示“Welcome!”。 #include<iostream.h> //包含头文件 int main() //程序入口函数 { //程序开始 char str[]="Hello,World!"; //定义一个字符数组并初始化 cout<<str<<endl; //在屏幕上输出字符串内容并换行 return 0; } //程序结束
2.2.2 C++程序的结构特性 类的声明部分 面向对象程序 类的使用部分
例2.2 典型的C++程序结构 #include<iostream.h> // 类的声明部分 class A{ int x,y,z; //类A的数据成员声明 … fun(){ … } //类A的成员函数声明 … }; // 类的使用部分 int main() { A a; // 创建一个类A的对象a … a.fun(); // 给对象a发消息,调用成员函数fun() return 0; }
2.2.3 C++程序的编辑、编译和运行 C源程序文件扩展名为.C,而C++源程序文件扩展名为.CPP。 在DOS下,C++程序的编辑、编译及运行方法和过程与C语言基本一样,如Turbo C++或Borland C++都有带C和C++两种编辑器,当源程序文件扩展名为.C时,启动C编译器,当源程序文件扩展名为.CPP时启动C++编译器。 在Windos下,我们常用Visual C++开发环境,来编辑、编译和运行C++程序。
2.3 C++在非面向对象方面的扩充 2.3.1 注释与续行 以下两条语句是等价的: x=y+z; /* This is a comment */ x=y+z; //This is a comment C++的“//”注释方式特别适合于内容不超过一行的注释,这时,它显得很简洁。 C++中还引入了一个续行符“\”(反斜杠)。这样,当一个语句太长时可以用该符号把它分段写在几行中。它的用法是写在一行的最后,就表示下一行为续行。
2.3.2 输入输出流 把与数据传送有关系的事务叫做流。有时候,流还可以代表要进行传送的数据的结构、属性和特性,用一个名字来表示,叫做流类;而用流代表输入设备和输出设备,叫做流的对象。
2.3.2 输入输出流 1.用cout进行输出 cout必须和输出运算符(插入运算符)“<<”一起使用。“<<”在这里不作为位运算的左移位运算符,而是起插入的作用, 例如:cout<<”Hello!\n”的作用是将字符串”Hello!\n”插入到输出流cout中,也就是输出在标准输出设备上。
2.3.2 输入输出流 例2.3 使用cout输出不同变量 #include<iostream.h> int main() { int i=10,j=45; double x=56.83,y=534.65; char *str=”Windows!”; cout<<”i=”<<i<<” j=”<<j<<’\n’; cout<<”x=”<<x<<” y=”<<y<<endl; cout<<”str=”<<str<<’\n’; return 1; }
2.3.2 输入输出流 运行结果为: i=10 j=45 x=56.83 y=534.65 str=Windows! 如将上面的输出语句改为 (注:必须包含头文件iomanip.h) cout<<”i=”<<setw(6)<<i<<” j=”<<setw(6)<<j<<’\n’; cout<<”x=”<<setw(6)<<x<<” y=”<<setw(6)<<y<<endl; cout<<”str=”<<setw(6)<<str<<’\n’; 输出结果为 i= 10 j= 45 x= 56.83 y=534.65 str=Windows!
2.3.2 输入输出流 2.用cin进行输入 输出流是指输入设备向内存流动的数据流。标准输入流cin是从键盘向内存流动的数据流。用“>>”运算符从输入设备键盘取得数据送到输入流cin中,然后送到内存。 “>>”常称为“提取运算符”。
2.3.2 输入输出流 例如: int i; float x; cin>>i>>x; 在输入时只需输入下面形式: 23 56.78 注意问题: ① 不同类型的变量一起输入时,系统除检查是否有空白外,还检查输入数据与变量的匹配情况。 ② 在输入字符串时,字符串中不能有空格,一旦遇到空格,就当作是本数据结束。 注:输入数据用空格或换行做分隔符
2.3.2 输入输出流 3.说明 (1)使用cin或cout进行I/O操作时,在程序中必须嵌入头文件iostream.h,否则编译时要产生错误。 (2)前面用cout和cin输出输入数据时,全部使用了系统缺省的格式。 例2.4 操作符dec、hex、和oct的使用 #include<iostream.h> int main() { int x=25; cout<<hex<<x<<” ”<<dec<<x<<” ”<<oct<<x<<’\n’; return 1; }
2.3.3 用const定义常变量 定义:常量是指用以表达有固定数值或字符值的单词符号,在程序中不允许修改。 const与#define区别 const定义常量:具有变量的属性,有数据类型,占用存储单元,有地址,可以用指针指向它,只是在程序运行期间此变量的值是固定的,不能改变。 宏定义:只是在预编译时进行字符置换,在预编译之后,程序中不再有宏定义标识符。这个标识符不是变量,没有类型,不占存储单元,而且不安全。
2.3.3 用const定义常变量 1.指向常量的指针(const int *p) 是指一个指向常量的指针变量。此种情形下通过间接引用指针不可改变变量的值,假设指针为p,则*p不可变。 例如: const int a=1; const int b=2; int i = 3,j=4; const int *pi = &a; //合法 或int const *pi = &a; 注:const int 与int const等价
2.3.3 用const定义常变量 说明: (1)可以将变量指针或常量指针赋值给该指针; 例如: const int *pi = &i; //合法,pi赋变量的地址 const int *pi = &a; //合法,pi赋值常量的地址 (2)该指针的值可变,其表达的变量的值不可变; pi=&j;或pi=&b;//合法 pi++;或pi--;//合法 *pi=8;//出错 (3)为了便于记忆可以从右往左读。 例如: const char * pc: pc is pointer to const char
2.3.3 用const定义常变量 2.常指针(int * const p) 指针指本身,而不是指向的对象(变量)声明为常量。这种情形下,指针本身为常量,不可改变,任何修改指针本身的行为都是非法的。 说明: (1)只能将变量指针赋值给该指针; 例如: int* const pi = &i;//合法 int* const pi = &a;//出错 (2)指针是常量,不可变。指针所指变量(*pi)值可变; pi = &j; //出错 *pi = a; //合法 (3)为了便于记忆可以从右往左读。 例如: char * const pc: pc is const pointer to char
2.3.3 用const定义常变量 3.指向常量的常指针(const int * const p) 这个指针本身不能改变,它所指向的值也不能改变。设有指针p,此种情形下,p和*p都不可变。 说明: (1)可以将变量指针或常量指针赋值给该指针; const int * const pi = &i; //合法 const int * const pi = &a; //合法 (2)指针是常量,不可变。指针所指变量(*pi)值不可变; pi = &b; //出错,pi不可变 pi = &j; //出错,pi不可变 *pi = b; //出错,*pi不可变 *pi = j; //出错,*pi不可变 pi++; //出错,pi不可变
2.3.4 函数原型声明 1.函数声明 函数声明是为了让编译器知道在函数使用之前函数的意图。 在函数声明时,要写出函数的返回值类型、函数名、参数类型。 2.函数的定义 函数只有定义之后才能使用。函数的定义就是要写出函数完成特定功能所需要的代码。 3.函数原型 定义了返回数据类型、函数名字以及函数参数数据类型。 int sum(int x,inty) //sum函数原型声明 int sum() //没有列出sum函数的参数 sum() //sum是整型函数,可以省略函数类型
2.3.5 函数重载 C++允许在同一作用域中用同一函数名定义多个函数,这些的参数个数和参数类型不相同,这些同名的函数用来实现不同的功能,这就是函数的重载。 函数重载要求编译器能够唯一地确定调用一个函数时应执行哪个代码,即采用哪个函数实现。确定函数实现时,要求从函数参数的个数和类型上来区分。因此,不能通过返回类型来区分。 1.参数类型上不同的重载函数
例2.5参数类型不同的重载函数 #include <iostream.h> int add(int, int); double add(double,double); void main() { cout<<add(5, 0)<<endl; cout<<add(5.0,10.5)<<endl; } int add(int x,int y) { return x+y; } double add(double a,double b) { return a+b; }
2.参数个数不同的重载函数 例2.6参数个数上不相同的重载函数 #include <iostream.h> int min(int a,int b); int min(int a,int b,int c); int min(int a,int b,int c,int d); void main() { cout<<min(13,5,4,9)<<endl; cout<<min(-2,8,0)<<endl; } int min(int a,int b) { return a<b?a:b; } int min(int a,int b,int c) { int t = min(a,b); return min(t,c); } int min(int a,int b,int c,int d) { int t1=min(a,b); int t2=min(c,d); return min(t1,t2);}
2.3.5 函数重载 说明: (1)返回类型不在参数匹配检查之列。若两个函数返回类型不同外,其他均相同,则是非法的。 (2)函数的重载与带缺省值的函数一起使用时,有可能引起二义性,。 (3)在函数调用时,如果给出的实参和形参类型不相符,C++的编译器会自动做类型转换工作。如果转换成功,则程序继续执行,但在这种情况下,有可能产生不识别的错误。
2.3.7 带有缺省参数的函数 在C++中,允许在函数的说明或定义时给一个或多个参数指定缺省值。这样在调用时,可以不给出参数,而按指定的缺省值进行工作。 例如有一函数原型说明为: int init(int x=5,int y=10); 则x与y的缺省值分别为5与10。 以下的函数调用都是允许的: init(100,80); // x=100,y=80 init(25); // x=25,y=10 init(); // x=5,y=10
2.3.7 带有缺省参数的函数 说明: (1)函数可以重新说明使原来不带缺省值的参数带上缺省值,但已经指明缺省值的参数不能重新说明。 #include<iostream.h> void initialize(int printNo,int state=0); //重新说明printNo的缺省值,state保留原缺省值 void initialize(int printNo=1,int state); void main() { initialize(); initialize(0); initialize(1,1); } void initialize(int printNo,int state) { cout<<”printNo=”<<printNo<<”,”; cout<<”state=”<<state<<endl; }
2.3.7 带有缺省参数的函数 (2)当一个函数中有多个缺省值时,则形参分布中缺省值参数应从右到左逐渐定义。 例如,以下函数说明不正确: Fun(int par1=1,int par2,int par3=3); Fun(int par1=1,int par2=2,int par3); Fun(int par1,int par2=2,int par3); 当出现Fun(7)或Fun(5,6)系统无法判断哪一个缺省。
2.3.8 变量的引用 1. 引用的概念 引用通常被认为是某个变量的别名,声明一个引用的格式如下: 数据类型 & 引用名 = 已定义的变量名; 例如: int i=5; int & j=i; 这里,j是一个整数类型的引用,用整型变量i对它进行初始化,这时j就可看作是变量i的别名 。 注:引用不是值,不占存储空间,声明引用时,所引用的变量的存储状态不会改变。引用只有声明,没有定义。
2.3.8 变量的引用 例2.9取引用地址 #include <iostream.h> void main() { int intOne; int& rInt=intOne; intOne=5; cout <<"intOne:" <<intOne <<endl; cout <<"rInt:" <<rInt <<endl; cout <<"&intOne:" <<&intOne <<endl; cout <<"&rInt:" <<&rInt <<endl; }
2.3.8 变量的引用 3. 引用的说明 (1)除了用作函数的参数或返回类型,引用必须在声明时用某一种类型的变量或已定义的引用对它初始化。例如: int &b;//错误 float a;int &b=a;//错误 int a=5; int &b=a; //合法 int &c=b;//合法
2.3.8 变量的引用 (2)引用初始化后不能重新声明。例如 int a=3,b=4; int &c=a;//合法 int &c=b;//错误 (3)除在声明时“&”作为引用运算符,其他场合使用“&”都是取地址操作符。例如: int a=5; int &b=a; int *pi=&a;
2.3.8 变量的引用 (4)不能建立“void”类型的引用。例如 void &a=9;//错误 (5)不能建立引用数组。例如: char c[6]=“Hello”; char &rc[6]=c;//错误 (6)可以建立指针变量的引用。例如: int i=5; int *p=&i; int *&pt=p; 注:指针变量的引用写成“ * &pt”而不是“&*pt”。
2.3.8 变量的引用 (7)不能建立引用的引用。例如 int a; int &&b=a;//错误 (8)可以用“const”对引用限定,不能修改引用的值。例如: int a=5;const int &b=a; b=3;//错误 a=3;//合法 (9)可以用常量或表达式对引用初始化,但必须用“const”作声明。例如: int i=5;const &a=i+3;//合法 double d=3.14159; const int &a=d;//合法 double d=3.14159;int &a=d;//错误
4. 引用作函数参数 例2.12 利用“引用参数”实现两个变量的值互换。 #include<iostream.h> void swap(int &a,int &b) { int temp; temp=a; a=b;b=temp; } int main() { int i=3,j=5; swap(i,j); cout<<"i="<<i<<" j="<<j<<endl; return 1; } 注:C++提供引用主要用途就是将引用作函数参数
5. 引用返回函数的值 例2.20 利用返回引用实现值的传递。 #include<iostream.h> int & B(int &n) { n++; return n; } int main() { int a = 10; int &b = B(a); cout << b << endl; cout << a << endl; cout<<&a<<endl; cout<<&b<<endl; B(a)++; cout<<a<<endl; }
2.3.9 内联函数 调用函数时需要一定时间,如果有的函数需要频繁使用,则累计所用时间会很长,从而降低程序的执行效率 C++提供一种提高效率的方法,即在编译时将所调用函数代码嵌入到主程序中。这种嵌入到主函数中的函数体称为内联函数(inline function)。
2.3.9 内联函数 例2.15 内联函数的使用 #include <iostream.h> inline double circle(double r) // 内联函数 { return 3.1416*r*r; } int main() { for (int i=1;i<=3;i++) cout<<"r="<<i<<" area= "<<circle(i)<<endl; return 0; }
2.3.9 内联函数 使用内联函数要注意问题: 1.先声明后使用。 2.内联函数的函数体限制。 • 不能含有复杂的结构控制语句,如“switch”和“while”。 • 递归函数是不能被用来做内联函数 3.C++中尽可能使用内联函数取代宏定义。
2.3.10 作用域标识符∷ 例2.21 使用作用域标识符的情况。 #include<iostream.h> int avar; main() { int avar; avar=25; // 局部变量avar ::avar=10; // 全局变量avar cout<<"local avar ="<<avar<<endl; cout<<"global avar ="<<::avar<<endl; return 0; } 程序运行结果如下: local avar=25 global avar=10
2.3.11 字符串变量 C++中除了使用字符串数组处理字符串外,还提供了一种更方便的方法——用字符串类型(string类型)定义字符串变量。优点是因为不必担心内存是否足够,字符串长度等,而且作为一个类出现,它集成的操作函数足以完成大多数情况下的需要。
2.3.11 字符串变量 1.声明字符串变量: string str1; string str2="China"; 为了在程序中使用“string”类型,必须包含头文件<string>。注意:不是string.h,string.h是C字符串头文件。如果在Visual C++6.0以上使用,必须加上命名空间,如: #include<iostream>//不能加.h using namespace std;
2.3.11 字符串变量 2.字符串变量的输入输出 #include <iostream> //注意不是iostream.h#include <string>using namespace std;int main(){ string s; cin>>s; cout<<s<<endl; return 0; } 注意: ①读取并忽略开头所有的空白字符(如空格,换行符,制表符) ②读取字符直至再次遇到空白字符,读取终止。
2.3.11 字符串变量 3.字符串变量的赋值 str1=“China”; //合法 char str[30]; str=“China”; //错误 向字符串变量赋值时不必精确计算字符个数,不必顾虑是否会“超长”而影响系统安全,为使用者提供了很大方便。可以对字符串变量中的某一个字符进行操作,例如: string word="Then"; word[2]='a'; //这里,将e换成了a
2.3.11 字符串变量 4.两个字符串变量相加 字符串“string”变量的加法被定义为连接。也就是说,两个或多个string变量可以通过使用加操作符“+”或者复合赋值操作符“+=”连接起来。 string s1="hello,"; string s2="world\n"; string s3=s1+s2; //s3是"hello,world\n" 也可以 string s1="hello"; string s2="world"; string s3=s1+","+s2+"\n";
2.3.11 字符串变量 4.两个字符串变量相加 当进行"string"变量和字符串字面值混合连接操作时,“+”操作符的左右操作数必须至少有一个是"string"类型的: string s1=“hello”; string s2=“world”; string s3=s1+“,”; //合法string s4=“hello”+“,”; //错误string s5=s1+“,”+“world”; //合法string s6=“hello”+“,”+s2; ;//错误
2.3.11 字符串变量 5.用关系运算符实现字符串比较: 比较两个字符串的大小实际上是比较每个字符串中字符。字符串比较运算区分大小写,即同一个字符的大小写形式被认为是两个不同的字符。 关系操作符比较两个“string”对象时采用策略: ①如果两个"string"对象长度不同,且短的string对象与长的string对象的前面部分相匹配,则短的string对象小于长的string对象; ②如果两个string对象的字符不同,则比较第一个不匹配的字符。
2.3.12 new和delete C语言中是利用库函数“malloc”和“free”分配和撤销内存空间的。但是使用“malloc”函数有两个缺陷: (1)必须指定需要开辟的内存空间的大小。其调用形式为“malloc(size)”。 (2)其返回值一律为void *型,必须再程序中进行强制类型转换,才能使其返回的指针指向具体的数据。 C++提供了简便而功能较强的运算符new和delete来取代malloc和free函数。
2.3.12 new和delete 1.动态分配内存运算符new new后面跟一个数据类型,并跟一对可选的方括号[ ],里面为要求的元素数。它返回一个指向内存块开始位置的指针,形式为: pointer = new type 或者 pointer = new type[elements] 例如: new int; new int(20); new char [15];