第1、2章 绪论与C++对C的扩充
1.类与对象的基本概念:
在面向对象程序设计中,对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体。
类是对一组具有相同属性(或称状态,用数据表示)和行为(或称操作、方法,用函数实现)的对象的抽象,一个类所包含的方法和数据描述了一组对象的共同属性和行为。对象则是类的具体化,是类的实例。
在面向对象的程序设计中,总是先声明类,再由类生成其对象,类是建立对象的“模板”,按照这个模板所建立的一个个具体的对象,就是类的实际例子,通常称为实例。
2.面向对象程序设计方法的3个主要特点:
(1)封装性:在面向对象程序设计中,封装是指把数据和实现操作的代码集中起来放在对象内部,并尽可能隐藏对象的内部细节。面向对象程序设计是通过类的说明实现封装的。程序在使用一个对象时,只能通过对象与外界的操作接口来操作它。在C++中,成员函数名就是对象的对外接口。外界可以通过函数名来调用这些函数实现某些行为。
(2)继承性:体现在类的层次关系中,派生的子类拥有父类中定义的数据和方法。子类直接继承父类的全部描述,同时可修改和扩充,并且继承具有传递性。
(3)多态性:对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行动,这种现象称为多态性。利用多态性,用户可发送一个通用的信息,而将所有的实现细节都留给接受消息的对象自行决定,这样,同一消息即可调用不同的方法
3.C++对C的补充
(1)输入输出头文件:
#include<iosteam> using namespace std;//使用命名空间std
(2)main()函数
标准C++要求main函数必须声明为int类型。main函数执行完毕通常返回给操作系统一个值。该值是一个状态指示器,操作系统一般通过main()的返回值来确定程序是否执行完毕。
int main(){ …
return 0;
}
(3)C++中的输出流
cout输出流可向输出设备输出若干个任意类型的数据。
cout必须配合插入操作符“<<”使用,用于向输出流中插入数据,引导待输出的数据输出到屏幕上。
格式:cout<<输出项1<<输出项2<<….<<输出项n;、
“输出项”是需要输出的一些数据,可以是变量、常量或表达式。
在cout中使用endl或转义字符′\n′作为输出项,可实现数据的换行功能。
(4)C++中的输入流
在C++中,数据的输入通常采用输入流对象cin来完成。
格式:cin>>变量1>>变量2>>……>>变量n;
cin必须配合抽取操作符“>>”使用,用于从输入数据流中抽取数据传送给“>>”后面的变量,从而实现在程序运行时为变量赋值。
(5)const修饰符:
①C++:使用const定义常值变量。
格式:const 类型标识符 常值变量名=常量值;
声明const变量时必须通过初始化获得初值
②指向常量的指针:指针指向空间的内容是不能改变的
const int *p; int *u; *p=10; //╳ 因为p指向的是常量,其所指空间的内容不可修改 p=u; //√ ③常指针:定义时必须初始化,且一旦初始化,就不能再指向其他变量 int d = 1; int* const w = &d; *w=2; // OK w=p; //╳ 因为p是一个常指针,其所指空间地址不可修改
④指向常量的常指针:定义时必须初始化,不能再指向其他变量,且指针指向空间的内容是不能改变的。
int d = 1; const int* const w = &d; *w=2; // ╳ 因为w指向的是常量,其所指空间的内容不可修改 w=p; //╳ 因为w是一个常指针,其所指空间地址不可修改 ⑤const修饰形参:表示此参数在其所在的函数内为常量,即不可修改。
(6)函数的使用
①形参带默认值:在调用函数时,可以不用给带默认值的形参传递实参。
如:
void myfunc(double d=0.0){ …} myfunc(198.234); // pass an explicit value myfunc( ); // let function use default
默认参数通常在函数名第一次出现时指定,一般是在函数原型声明中设置,在函数定义时不再写出。若程序中只有函数定义而没有函数声明,则默认参数可出现在函数定义中。
如果一个函数中有多个默认参数,则在形参分布中,默认参数应按从右至左的顺序依次定义,即在带默认值的形参的右边不能出现不带默认值的形参。
②内联/内嵌函数:在函数声明或定义的前面加上关键字“inline”,该函数就被声明为内联函数。inline限定符只用于经常使用的短函数。
③函数重载
两或两个以上的函数使用同一个函数名,称为函数重载。
函数重载的条件: 函数参数的类型或个数不同,即函数原型的参数列表不同
只有函数返回值类型不同,不能重载
函数重载与参数带默认值的函数一起使用时,有可能引起二义性,使用时要谨慎。
(7)引用和引用参数
①概念:引用(reference)就是一个变量(目标)的别名,对引用的操作就是对目标的操作。
②语法格式: 类型标识符 &引用名=目标变量名;
例如:int a; int &aRef=a;
③说明:
系统并不为引用分配存储单元;
除了用作函数的参数或返回值类型外,在声明引用时,必须对其进行初始化。
为引用提供的初值,可以是一个变量或另一个引用。
一旦引用被声明为一个目标变量的别名,就不能把该引用名再作为其他变量的别名。
可以声明一个指针变量的引用:
不能建立数组、空指针、空类型(void)的引用。
不能建立引用的引用,不能建立指向引用的指针。
指针是通过地址间接访问某个变量(要使用*),而引用是通过别名直接访问某个变量。因而使用引用可以简化程序。
如果不希望通过引用改变原始变量的值,可声明常引用
const 类型标识符 &引用名=目标变量名;
④用引用作为函数的参数
定义函数时,函数的形参可以是基本数据类型的变量、指针变量、数组名,也可以是引用的形式。
调用该函数时,实参对应为主调函数中的变量。这样,被调函数可以通过引用对主调方的实参进行访问,甚至修改其值。
(8)作用域运算符:
C允许在不同的作用域内声明同名的变量,在作用域的重叠区域内,全局变量被局部变量屏蔽。
在C++中,可以通过使用作用域运算符(::)来访问重叠作用域内与局部变量同名的全局变量。
(9)new和delete运算符
①new运算符:用于向系统申请动态存储空间,并返回正确类型的指针。申请失败时,则返回0指针,使用new的语法格式:指针变量=new 数据类型标识符(初值)/[元素个数]
②delete运算符:使用new申请得到的空间必须使用delete运算符进行释放,使用格式:
delete []指针变量名
第3章 类与对象
1.类的定义:
类的定义包括类的说明和类的实现两大部分。说明部分提供了对该类所有数据成员和成员函数的描述;实现部分则提供了所有成员函数的实现代码。
(1)类定义的格式:
class <类名>
{ private:
<数据成员或成员函数>
protected:
<数据成员或成员函数>
public:
<数据成员或成员函数>
};
<各成员函数的实现代码>
(2)说明:
①class是定义类的关键字,类名由用户自己定义,但应满足标识符的命名规则。
②与struct相比,类的说明部分添加了新内容:成员函数的说明以及访问权限控制符:public、protected、private。
private部分:该部分成员只允许被本类的成员函数访问或调用,在类外不能被直接访问。一般情况下,类的数据成员多声明为private成员;
public部分:该部分成员允许被本类或其他类的成员函数(通过对象)访问或调用。
public成员多为成员函数,用来向外界提供一个接口,外界只能通过这个接口才可以实现对private成员的访问;一个类的定义中应该含有public权限的成员,否则该类的定义无意义。
protected部分:该部分成员不能在类外访问,只允许被本类的成员函数及其子类(派生类)的成员函数访问或调用。
当类成员未指明是哪部分时,默认为private成员。
类中的每个成员只能被指定一种特定的访问控制权限。
③公有部分、私有部分和保护部分可以以任意顺序出现,且并非同时出现。
④类的说明部分以分号结束。
(3)成员函数的定义:
①在类的定义体外部定义成员函数,在类的定义体中声明成员函数定义时,需在函数名之前加上其所属的类名和作用域限定符“::”,没加类名的函数默认为非成员函数(全局函数)。
②在类的定义体内部定义成员函数,系统自动使该成员函数成为内联函数。在类定义体外部定义的成员函数若为内联函数,需用inline关键字指明。
(4)类成员的访问:
①类的数据成员和成员函数属于该类的类作用域(即使成员函数定义在类体之外),非成员函数在文件作用域中定义。
②在类作用域中,类成员可由该类的所有成员函数直接访问;在类作用域外,访问类成员是通过一个对象的句柄实现的,可以是对象名、对象引用或对象指针。利用对象的句柄访问类成员的运算符与访问结构体成员的运算符相同。
2.对象
对象是类的一个实例,当定义一个类时,只定义了这种数据类型,当程序中定义了数据类型的变量时,该变量就是该类的对象(或类的实例)。
(1)类对象的定义方法:
定义类的同时定义对象;定义类后定义对象,单独定义对象的一般格式: 类名 对象名表;
(2)对象的指针与引用:
①指向对象的指针变量的定义格式: 类名 *变量名;
②对象引用的声明格式: 类名 &引用名=对象名;
(3)访问对象成员的方法:
①格式1:对象名.公有成员名;
②格式2:指针变量名->公有成员名;
注意:在类外不能对类的private成员和protected成员进行直接访问,可以通过其他public成员函数访问。
3.this指针
this指针是一个特殊的隐含指针,它指向当前对象,代表了对象的地址。当对象调用类的非静态成员函数时,编译器会自动将对象本身的地址作为一个隐含参数传递给该函数,这个地址被一个隐含的形参this指针获取,函数调用中对对象成员的访问都隐含地被加上了前缀this->。
显式使用this指针的语法格式: this->成员名;
4.构造函数
(1)功能:创建对象时,实现对数据成员的初始化。
(2)定义格式: 类名(形参列表) { 函数体 }
(3)特点:
①构造函数是类的成员函数,可以直接访问类的所有数据成员。
②构造函数与类同名,可以是无参函数,也可以是有参函数。
③构造函数不允许有返回值类型,即使是void也不可以。
④构造函数可以重载,为对象提供不同的初始化方法。
⑤构造函数应为公有函数(public)。
⑥声明类对象时,可以在对象名后面的括号中提供初始化值。这些初始化值作为参数传递给类的构造函数。
⑦在创建类对象时,系统将自动调用构造函数以实现对数据成员的初始化。
⑧若类中没有显式定义构造函数,则编译时系统为该类提供一个默认的构造函数,它仅负责创建对象,不做任何初始化工作。在用默认构造函数创建对象时,若创建的是全局对象或静态局部对象,则对象的默认值是0,否则对象的初始值不确定。如果用户自定义了构造函数,则编译系统将不会再添加默认的构造函数。
⑨构造函数可以包含默认参数,这样即使对象定义时不提供初始值,对象也能利用默认参数进行初始化。一个类只能有一个带默认参数的构造函数,在使用时要防止二义性。
(4)拷贝构造函数
①功能:拷贝构造函数是一种特殊的构造函数,用于完成基于对象的同一类其他对象的构造及初始化。
②定义格式:
类名(const 类名 &参数名)
{ 函数体 }
③说明:
拷贝构造函数只有一个参数,即该类对象的引用;
拷贝构造函数的功能是用于实现对象值的拷贝,以完成对新对象的初始化,即用一个对象去构造另一个对象。
如果定义类时没有定义拷贝构造函数,编译系统会自动为类添加一个默认的拷贝构造函数,用以完成浅拷贝。
如果将对象作为函数的参数,或将对象作为函数的返回值,调用这两类函数时也会自动调用拷贝构造函数。
(5)对象的赋值:与变量的赋值类似,同类型的对象之间也可以进行赋值,对象的赋值是指对其中的数据成员赋值,不包括成员函数的赋值。
5.析构函数
(1)功能:
析构函数是类的一个特殊的成员函数,在类对象的生命期即将结束时由系统自动调用,用来在对象被删除前做一些清理善后工作和数据保存工作。其函数名是在类名前面加上代字符(~)。
(2)定义格式:
~类名()
{ 函数体 }
(3)特点:
①析构函数没有返回值,也没有参数。
②一个类中只能有一个析构函数,没有重载。
③如果定义类时没有提供析构函数,系统会自动创建一个默认的析构函数。当类对象中分配有动态内存时,则必须为该类提供适当的析构函数,以完成清理工作。