第二章C++基本知识速成 第一章已经从总体概念及基本原则等方面对面向对象程序设计进行了简要的介绍,之后 我们将逐步推进,讨论面向对象编程(OOP)的实现。本章对C++语言的基本知识进行说明 分析,帮助初学者尽快学会使用C+语言进行面向对象程序设计。 本章目的 介绍C++的词法符号( token) 了解C++程序基本框架 总览C++数据类型 掌握C++运算符及表达式 了解C++常量、变量的表示和用法 掌握程序流程控制基本语句 2.1.1C++的面向对象特征 概括地讲,面向对象系统包含3个要素:对象、类和继承。能支持所有上述3个方面的 语言,被称为面向对象语言。从本质上讲,C++并不是一种完美的面向对象设计语言,而是 C语言的一个超集,与C兼容也是其成功的一个重要方面,因而C++也是一种混合语言,既 支持传统的面向过程程序设计,又支持面向对象程序设计,灵活性大。它继承了传统C语言 的优点,克服了其不足;又在面向对象特征及非面向对象特征这两个方面增加了新功能,使 得它既适用于结构化程序设计,又能满足面向对象程序设计的要求,符合广大程序设计逐步 更新其程序设计观念和方法的要求,因而很快流行起来 的面向对象特征和风格 (1)C++借助于把一个数据结构及其操作函数组合在一起,提供了类/对象的构造和封 装机制 定义一个类的一般形式是 class calss name ∥有成员部分(类外部的代码不能直接访问的部分) data and methods ∥包括成员变量和成员函数 protected ∥保护的成员部分 public ∥公用成员部分 data and methods ∥公有部分定义的变量和函数 在缺省关键词的情况下,类中所有项均为私有的。C++中的 struct和 union也和 class 一样能够定义一个类,所不同的是定义成员时,在缺省关键词的情况下所有成员均为公有的。 (2)提供对象的创建和删除,特别是使用了构造函数和析构函数来管理对象 构造函数是一个特殊的成员函数,其函数命名与类名同名,它指定了一个类的实例对 象的建立和初始化过程
第二章 C++基本知识速成 第一章已经从总体概念及基本原则等方面对面向对象程序设计进行了简要的介绍,之后 我们将逐步推进,讨论面向对象编程(OOP)的实现。本章对 C++语言的基本知识进行说明 分析,帮助初学者尽快学会使用 C++语言进行面向对象程序设计。 本章目的: .介绍 C++的词法符号(token) .了解 C++程序基本框架 .总览 C++数据类型 .掌握 C++运算符及表达式 .了解 C++常量、变量的表示和用法 .掌握程序流程控制基本语句 2.1.1 C++的面向对象特征 概括地讲,面向对象系统包含3个要素:对象、类和继承。能支持所有上述3个方面的 语言,被称为面向对象语言。从本质上讲,C++并不是一种完美的面向对象设计语言,而是 C语言的一个超集,与C兼容也是其成功的一个重要方面,因而C++也是一种混合语言,既 支持传统的面向过程程序设计,又支持面向对象程序设计,灵活性大。它继承了传统C语言 的优点,克服了其不足;又在面向对象特征及非面向对象特征这两个方面增加了新功能,使 得它既适用于结构化程序设计,又能满足面向对象程序设计的要求,符合广大程序设计逐步 更新其程序设计观念和方法的要求,因而很快流行起来。 C++的面向对象特征和风格: (1)C++借助于把一个数据结构及其操作函数组合在一起,提供了类/对象的构造和封 装机制。 定义一个类的一般形式是: class calss_name { private: //私有成员部分(类外部的代码不能直接访问的部分) data and methods //可包括成员变量和成员函数 protected: //保护的成员部分 data and methods public: //公用成员部分 data and methods //公有部分定义的变量和函数 }object_name_list; 在缺省关键词的情况下,类中所有项均为私有的。C++中的 struct 和 union 也和 class 一样能够定义一个类,所不同的是定义成员时,在缺省关键词的情况下所有成员均为公有的。 (2)提供对象的创建和删除,特别是使用了构造函数和析构函数来管理对象。 构造函数是一个特殊的成员函数,其函数命名与类名同名,它指定了一个类的实例对 象的建立和初始化过程
析构函数是用于释放内存和删除由构造函数创建的对象。 例:EX11CPP #include <iostream h ∥不同于C的 stdio h class class ablin myclasso oid showO myclass: myclass( cout<<""in constructor\n ∥ou:用于处理标准输出 它将输出流中的数据发送到标准输出设备(显示器)上 ∥<:将数据插入到输出流中。 ∥a的值由 myclass()自动初始化 ∥注意,构造函数是没有返回值的 void myclass showo cout<<a<<endl maino myclass ob;∥变量说明语句也是动作语句,调用了构造函数 ob. show) return 0 其中:COUT为标准输出流〈 (3)能够进行对象间的消息传递、操作调用,除了使用操作符、指针、表达式外,还有 指向自身的this等。 (4)支持继承机制,特别是提供了在一种通用的功能上进行具体化定义的方法,使用 基类和派生类,形成了十分方便的继承机制。 在C++中,一个派生类可以有多个基类,支持多重继承。说明一个类继承另一个类的形 式为 class派生类名:[ public/private/ protected基类名 ∥冒号是类属范围算符(双目)
析构函数是用于释放内存和删除由构造函数创建的对象。 例:EX1_1.CPP #include //不同于 C 的 stdio.h class myclass { int a; public: myclass(); void show(); }; myclass::myclass() { cout<<”in constructor\n”; //cout:用于处理标准输出, //它将输出流中的数据发送到标准输出设备(显示器)上。 //<<:将数据插入到输出流中。 a=10; //a 的值由 myclass()自动初始化 } //注意,构造函数是没有返回值的 void myclass::show() { cout<<a<<endl; } main() { myclass ob ; //变量说明语句也是动作语句,调用了构造函数 ob.show(); return 0; } 其中:COUT 为标准输出流〈〈 (3)能够进行对象间的消息传递、操作调用,除了使用操作符、指针、表达式外,还有 指向自身的 this 等。 (4)支持继承机制,特别是提供了在一种通用的功能上进行具体化定义的方法,使用 基类和派生类,形成了十分方便的继承机制。 在 C++中,一个派生类可以有多个基类,支持多重继承。说明一个类继承另一个类的形 式为: class 派生类名:[public/private/protected] 基类名 { //冒号是类属范围算符(双目) . . . }
例:EXl2CPP class base Int x void setx(int n)(x=n void showxo( cout public 两种构造函数重载,使对象oba初始化,而obb没有 myclass((x=0; i //no initializer myclass( int n)(x=n //initialize int getxofreturn x; i myclass oba( 10); //declare with initial value myclass obb l/declare without initializer cout<<”oba:”<< oba getx(<n
例:EX1_2.CPP class base { int x; public: void setx(int n){x=n;} void showx(){cout class myclass { int x; public: //两种构造函数重载,使对象 oba 初始化,而 obb 没有 myclass(){x=0;} //no initializer myclass(int n){x=n;} //initializer int getx(){return x;} }; main() { myclass oba(10); //declare with initial value myclass obb; //declare without initializer cout<<”oba:”<<oba.getx()<<”\n”;
cout<<obb<<obb getxo<<n return 0 C++程序由函数和对象类组成,类在整体上代表一组对象的特征,声明类的目的上为了 建立对象。对象是在运行时存在的实体(例),由类模板创建所需的对象时,一个特殊的成 员函数(构造函数)被自动执行,以初始化建立的对象 类代表由抽象分析所认识到的真实世界的概念对象,是语言中表达抽象的一个有力的工 具。 2.1.2C+语言对C语言在非面向对象方面的增强 C++除了继承传统C语言中的精华,并增加了许多的面向对象方面的特征之外,还在非 面向对象方面对C语言进行了增强 1、++提供了单行注释方式 传统的C语言中提供了块注释方式,其形式如下: /explanation setence 而在C++中,除保留块注释外,还增加了一种更方便的单行注释方式,其形式如下: //explanation sentence 2、更为灵活的变量说明 传统的C语言中,局部变量的说明必须放在可执行代码的前面。数据说明语句和可执 行语句的混合将引起编译错误。而在C++中,可以在程序代码块的任何地方进行局部变量的 说明,所说明变量的作用域是从对该变量进行说明的地方到该变量所在的最小分程序的未 尾 结构、联合和枚举名可直接作为类型名使用 在C语言中,在对结构、联合和枚举类型进行定义后,要生成该结构、联合和枚举类 型的变量,必须使用如下形式: struct struct name obj name union union name obj name emunmun name obj name 即必须在说明的结构、联合和枚举名的前面加上说明其所属类型的标识符。而在C++ 中,在对结构、联合和枚举类型进行定义后,该结构、联合和枚举名便可作为类型名使用, 可以直接用它进行对象定义。 4、枚举类型与整数关系 在C语言中,枚举值与整数值之间可以相互转换使用。而C++的类型检査则比C要严 格,枚举值将被自动转化为整型值使用,但将整型值转化为枚举值则需要进行强制类型转换, 否则会出现编译错误。如下面的一段代码,在C语言中都是可以接受的,但某些语句在C++ 中则会引起错误 mun name (John, Mike, Rose Joan mun name personl=John;
cout<<”obb”<<obb.getx()<<”\n”; return 0; } C++程序由函数和对象类组成,类在整体上代表一组对象的特征,声明类的目的上为了 建立对象。对象是在运行时存在的实体(例),由类模板创建所需的对象时,一个特殊的成 员函数(构造函数)被自动执行,以初始化建立的对象。 类代表由抽象分析所认识到的真实世界的概念对象,是语言中表达抽象的一个有力的工 具。 2.1.2 C++语言对 C 语言在非面向对象方面的增强 C++除了继承传统 C 语言中的精华,并增加了许多的面向对象方面的特征之外,还在非 面向对象方面对 C 语言进行了增强。 1、 ++提供了单行注释方式 传统的 C 语言中提供了块注释方式,其形式如下: /*explanation setence */ 而在 C++中,除保留块注释外,还增加了一种更方便的单行注释方式,其形式如下: //explanation sentence 2、更为灵活的变量说明 传统的 C 语言中,局部变量的说明必须放在可执行代码的前面。数据说明语句和可执 行语句的混合将引起编译错误。而在 C++中,可以在程序代码块的任何地方进行局部变量的 说明,所说明变量的作用域是从对该变量进行说明的地方到该变量所在的最小分程序的未 尾。 3、结构、联合和枚举名可直接作为类型名使用 在 C 语言中,在对结构、联合和枚举类型进行定义后,要生成该结构、联合和枚举类 型的变量,必须使用如下形式: struct struct_name obj_name; union union_name obj_name; emun emun_name obj_name; 即必须在说明的结构、联合和枚举名的前面加上说明其所属类型的标识符。而在 C++ 中,在对结构、联合和枚举类型进行定义后,该结构、联合和枚举名便可作为类型名使用, 可以直接用它进行对象定义。 4、枚举类型与整数关系 在 C 语言中,枚举值与整数值之间可以相互转换使用。而 C++的类型检查则比 C 要严 格,枚举值将被自动转化为整型值使用,但将整型值转化为枚举值则需要进行强制类型转换, 否则会出现编译错误。如下面的一段代码,在 C 语言中都是可以接受的,但某些语句在 C++ 中则会引起错误。 emun name {John,Mike,Rose,Joan}; emun name person1=John;
mun name person3=1 l/This is an error in C++ mun name person4=(emun name)l 5、C++增加了无名联合类型 无名联合是C++中提供的一种特殊联合,可以用来说明一组无标记名的、共享同一内 存地址的数据项。例如 union Int 1: float f 无名联合可以通过使用其中数据项名字直接进行访问。(?) 6、作用域限定运算符: 作用域限定运算符::用于对当前作用域之外的同名变量进行访问。如在下面的例子中, 在局部变量var的作用域内使用 来实现对全局变量var的访问 例:EX14CPP #include Int var void maino float var ∥局部变量var var=6 ∥局变量var cout<< local variable var=”<<var<<n” cout<<globle variable var=<<:var<<"n 7、函数调用时的参数传递方式 在C语言中,函数调用时的参数传递是用按值传递方式进行的,在子函数中对形参的 改变并不引起实参的数值改变。而在C++中,函数调用时的参数传递是用按地址传递方式进 行的,形参和实参所指向的是同一内存区域的内容,因此在了函数中对形参的修改将会导致 实参的数值变化 8、增强了类型转换方式 在C++中,除保留了传统C语言的强制类型转换方式外,还可以将类型名作为函数名 使用,这将大大提高程序的可读性。例如 float f=0. 01 long k=long();∥将类型名作为函数名用 9、void类型 在C+中,、void类型指针是可以与任何类型指针相匹配的指针。Void类型指针可以被赋
emun name person2=person1; emun name person3=1; //This is an error in C++! emun name person4=(emun name)1; 5、C++增加了无名联合类型 无名联合是 C++中提供的一种特殊联合,可以用来说明一组无标记名的、共享同一内 存地址的数据项。例如: union { int i; float f; }; 无名联合可以通过使用其中数据项名字直接进行访问。(?) 6、作用域限定运算符:: 作用域限定运算符::用于对当前作用域之外的同名变量进行访问。如在下面的例子中, 在局部变量 var 的作用域内使用::var 来实现对全局变量 var 的访问。 例:EX1_4.CPP #include int var; void main() { float var; var=3.14; //局部变量 var ::var=6; //全局变量 var cout<<”local variable var=”<<var<<”\n”; cout<<”globle variable var=”<<::var<<”\n”; } 7、函数调用时的参数传递方式 在 C 语言中,函数调用时的参数传递是用按值传递方式进行的,在子函数中对形参的 改变并不引起实参的数值改变。而在 C++中,函数调用时的参数传递是用按地址传递方式进 行的,形参和实参所指向的是同一内存区域的内容,因此在了函数中对形参的修改将会导致 实参的数值变化。 8、增强了类型转换方式 在 C++中,除保留了传统 C 语言的强制类型转换方式外,还可以将类型名作为函数名 使用,这将大大提高程序的可读性。例如: float f=0.01; long l=(long)f; long k=long(f); //将类型名作为函数名用 9、void 类型 在 C++中,void 类型指针是可以与任何类型指针相匹配的指针。Void 类型指针可以被赋
给任何类型的指针,从而可以避免许多无用的类型转换。而void型函数是无返回值的函数 它可以限制函数返回一个无用的int型数值 10、关键字 const 在C++中,关键字 const用于将一个标识符说明为常量,程序不能以任何方式对其进行 修改。而C++中的 const与C语言中# define有区别:cons所说明的常量是有内存单元与之 对应的量,在程序编译时其值还不能确定:而# define所说明的是在编译时便能确定其数值 的常量 关键字 const也可以用来修饰函数参数表中的某些参数,用以保证被修饰的参数对应的 实参在该函数内部不被改动。 当关键字 const用来修饰指针时,根据使用的形式不同,它可以冻结指针所指向的变量、 冻结指针本身或同时冻结指针用其所指向的变量,如下所示: const char *name=""Mike 冻结指针所指向的变量 char *const name=Mike” ∥(结指针本身 const char+ const name=Mke”,∥同时冻结指针及其所指向的变量 ll、类型兼容性 C++的类型匹配检查比C更为严格。在C中长度同为1字节的char、 unsigned char、 signed char型变量在相互赋值时可以不进行强制类型转换,而在C++中,则必须进行强制类型转换, 否则会出现编译错误。在类型兼容性方面的增强将大大提高程序的可移植性。 12、字符常量的大小 在C语言中,字符常量是按照整型进行处理的,它们的长度都是2B。而在C++中,整 型变量的长度仍为2B,但字符常量的长度只有1B,这便得C++程序占用内存空间更为节约 程序运行效率更高 和dele C++为了提高内存管理上的灵活性,提供了动态内存分配和释放的操作符new和 delete, 用来(代替)增强C语言中原有的函数 malloch和freO。 14、函数原型 在C++中,函数原型说明要求给出该函数的参数类型,这比传统的C语言的函数原型 说明更有利于编译系统检査非法参数调用,可以避免出现一些难于发现和调试的错误。 15、内联函数( inline) C++提供了内联函数。使用内联函数可以节约函数调用时保留现场所需的系统开销, 提高程序执行效率。同时,由于内联函数的使用将增大了程序的代码段,因此建议在使用时 充分权衡系统开销和程序代码段长度的关系,要谨慎使用。 16、缺省函数参数 在C++的函数调用时,可以缺省函数的参数。但是要使用函数参数,必须在函数定义 时为该参数赋一缺省值,且所缺省的参数的顺序只能是从左到右,不能随意缺省。例如: int function(int a=0; int b=l; int c=2;
给任何类型的指针,从而可以避免许多无用的类型转换。而 void 型函数是无返回值的函数, 它可以限制函数返回一个无用的 int 型数值。 10、关键字 const 在 C++中,关键字 const 用于将一个标识符说明为常量,程序不能以任何方式对其进行 修改。而 C++中的 const 与 C 语言中#dedfine 有区别:const 所说明的常量是有内存单元与之 对应的量,在程序编译时其值还不能确定;而#define 所说明的是在编译时便能确定其数值 的常量。 关键字 const 也可以用来修饰函数参数表中的某些参数,用以保证被修饰的参数对应的 实参在该函数内部不被改动。 当关键字 const 用来修饰指针时,根据使用的形式不同,它可以冻结指针所指向的变量、 冻结指针本身或同时冻结指针用其所指向的变量,如下所示: const char *name=”Mike”; //冻结指针所指向的变量 char *const name=”Mike”; //冻结指针本身 const char *const name=”Mike”; //同时冻结指针及其所指向的变量 11、类型兼容性 C++的类型匹配检查比C更为严格。在 C中长度同为 1字节的char、unsigned char、signed char 型变量在相互赋值时可以不进行强制类型转换,而在 C++中,则必须进行强制类型转换, 否则会出现编译错误。在类型兼容性方面的增强将大大提高程序的可移植性。 12、字符常量的大小 在 C 语言中,字符常量是按照整型进行处理的,它们的长度都是 2B。而在 C++中,整 型变量的长度仍为 2B,但字符常量的长度只有 1B,这便得 C++程序占用内存空间更为节约, 程序运行效率更高。 13、new 和 delete C++为了提高内存管理上的灵活性,提供了动态内存分配和释放的操作符new和delete, 用来(代替)增强 C 语言中原有的函数 malloc()和 free()。 14、函数原型 在 C++中,函数原型说明要求给出该函数的参数类型,这比传统的 C 语言的函数原型 说明更有利于编译系统检查非法参数调用,可以避免出现一些难于发现和调试的错误。 15、内联函数(inline) C++提供了内联函数。使用内联函数可以节约函数调用时保留现场所需的系统开销, 提高程序执行效率。同时,由于内联函数的使用将增大了程序的代码段,因此建议在使用时 充分权衡系统开销和程序代码段长度的关系,要谨慎使用。 16、缺省函数参数 在 C++的函数调用时,可以缺省函数的参数。但是要使用函数参数,必须在函数定义 时为该参数赋一缺省值,且所缺省的参数的顺序只能是从左到右,不能随意缺省。例如: int function(int a=0;int b=1;int c=2;) {
以下函数调用都是合 function l/equal to function(0, 1, 2) function( 12) /equal to function( 12, 1, 2) function(12, 13) equal to function( 12, 13, 2) 而以下函数调用则是非法的 function(, 12, 13) function( 12,, 13) 17、函数返回值 在C++中,任何说明为非vod类型的函数都需要指定一个相应类型的返回值,否则在 程序的编译时会产生警告错误
. . . } 以下函数调用都是合法的: function(); //equal to function(0,1,2) function(12); //equal to function(12,1,2) function(12,13); //equal to function(12,13,2) 而以下函数调用则是非法的: function(,12,13) function(12, ,13) 17、函数返回值 在 C++中,任何说明为非 void 类型的函数都需要指定一个相应类型的返回值,否则在 程序的编译时会产生警告错误