面向对象编程复习1函数调用形式•传值–传值调用是指在发生函数调用时,先计算实参表达式的值,并直接将各实参的值依次赋值给各形参。–单向传递,即由实参到形参;形参的值不能影响实参的值。•传地址调用–将实参的地址传递给形参。实参必须用地址值,形参用指针变量。–通过形参指针可以对实参进行间接读写。•引用调用–引用可以作为函数的返回值类型和形参,使用引用作为函数的形参时,主调函数的实参需要使用变量名。–函数调用时,将实参值传递给形参,实际上是被调用函数使用了实参的别名,因而形参的改变本质上就是对实参的改变。2内联函数•内联函数必须在函数第一次出现时由inline指定;•内联函数代码不宜太大,原则上适宜于1~5行代码的小函数,且该函数出现频率高;•不能含有复杂的分支或循环等语句;•递归调用的函数不能定义为内联函数。•类中定义的成员函数自动成为内联函数,若内联成员函数在类外实现,需要以inline限定。inline返回值类型函数名(形式参数表){函数语句序列}3带默认参数的函数•带默认参数的函数指在定义函数时给函数中的部分参数以默认值。–当调用语句给出函数的参数值时,就按给定值调用函数–当函数调用语句没有给出函数的参数值时,则按定义时的默认值调用函数–默认参数必须出现在右边,非默认参数在左边–默认参数应在函数第一次出现时给定默认值4作用域•函数原型作用域–函数原型声明中形参变量的作用域起于函数原型声明的左括号,结束于函数原型声明的右括号;•块作用域–从块内的定义处开始,直到该块结束为止。•函数作用域–函数中使用的语句标号具有函数作用域,仅在本函数中有效。•文件作用域–在函数之外声明的标识符具有文件作用域,其作用域开始于声明处,结束于该文件的结束处。5生存期•静态生存期:指变量或对象的生存期与程序的运行期同步,包括全局变量、静态全局变量和静态局部变量。•局部生存期:生存期开始于声明处,结束于作用域结束处,如局部变量。•动态生存期:除上述两种情况外的其余情况。具有动态生存期的变量或对象诞生于声明处,结束于该标识符作用域的结束处。一般情况下,动态生存期由运算符new和delete或函数malloc和free创建和释放。•static限定的局部变量称为静态局部变量。在整个程序的运行期间是存在的,但作用域却是局部的。6类对象的生存期•局部对象:是被定义在一个程序块或函数体内的对象,它的作用域范围小、生存期短。•静态对象:被定义在一个文件中,它的作用域从定义时开始到文件结束时止,它的作用域范围大,生存期也较长。•全局对象:其作用在域整个程序中,它的作用域范围最大、生存期也最长。7编译预处理•C++编译过程分分编译预处理和正式编译。•预处理指令均以#引导,每条预处理指令各占一行,没有分号结束符。•文件包含指令和条件编译指令是常用的编译预处理指令。•在C++中用const定义常量取代了C中的宏定义,用inline定义内联函数取代了C中的#define指令。8类成员访问控制表访问控制含义属性public公有成员类的外部接口protected保护成员仅允许本类成员函数及派生类成员函数访问private私有成员仅允许本类成员函数访问9类成员的访问•圆点访问形式–对象名.公有成员•指针访问形式–对象指针变量名-公有成员–(*对象指针变量名).公有成员10New运算符New运算符用于动态内存分配,使用形式如下:•指针所指向的数据类型应与new运算符后的数据类型相同,若申请成功则返回分配单元的首地址给指针变量,否则返回空指针值(即0)给指针变量。•动态分配了用于存放整型数据的内存空间,将初值写入该内存空间,并将首地址值返回指针变量。•动态分配了指定数组元素的数组,同时将存储区的首地址指针返回给指针变量。(1)指针变量=new数据类型;(2)指针变量=new数据类型(初始值);(3)指针变量=new数据类型[元素个数];11delete运算符•delete只能删除由new分配的堆内存;•对于一个指针只能使用一次delete操作;•当delete用于释放由new创建的数组连续内存空间时,指针变量名前必须使用一对方括号,而且方括号内没有数字。•使用形式:–delete指针变量名;–delete[]指针变量名;12构造函数•构造函数的函数名与类名相同;•构造函数可以有任意类型的参数,但没有函数返回值类型;构造函数可以重载;•若构造函数没有参数,则称为无参构造函数;若构造函数带有参数,则称为带参数构造函数;•构造函数在创建对象时由编译系统自动调用;•构造函数只能一次性地影响对象的数据成员初值。•每个类都必须有一个构造函数。如果程序没有显式定义构造函数,编译系统将自动生成一个默认形式的构造函数。13析构函数•析构函数不能有参数,也不能重载。•除对象生存期结束时自动调用外,在以下两种情况下析构函数会被调用:–如果一个对象被定义在一个函数体内,则当这个函数结束时。–若一个对象是使用new运算符被动态创建的,在使用delete运算符释放它时。•若没有显式定义析构函数,则系统自动生成一个默认形式的析构函数。14复制构造函数•功能:是用一个已知的对象初始化一个被创建的同类新对象;•复制构造函数有且仅有一个参数,即是同类对象的引用;•复制构造函数名与类名相同,并且没有返回值类型;•如果没有显式定义复制构造函数,系统自动生成一个默认形式的复制构造函数。•可以根据需要定义自己的复制构造函数,从而实现同类对象之间数据成员的值传递。15复制构造函数的定义格式class类名{public:类名(参数表);//构造函数类名(const类名&对象名);//复制构造函数┇};类名::类名(const类名&对象名){函数语句}16复制构造函数的调用•以下三种情况下由编译系统自动调用:–声明语句中用类的一个已知对象初始化该类的另一个对象时;–当对象作为一个函数实参传递给函数的形参时,需要将实参对象去初始化形参对象时,需要调用复制构造函数;–当对象是函数的返回值时,由于需要生成一个临时对象作为函数返回结果,系统需要将临时对象的值初始化另一个对象,需要调用复制构造函数。17浅复制与深复制•浅复制–在用一个对象初始化另一个对象时,只复制了数据成员,而没有复制资源,使两个对象同时指向了同一资源的复制方式称为浅复制;–默认复制构造函数所进行的是简单数据复制,即浅复制。•深复制–通过一个对象初始化另一个对象时,不仅复制了数据成员,也复制了资源的复制方式称为深复制;–自定义复制构造函数所进行的复制是深复制。18静态成员•静态成员提供了同一个类不同对象数据成员的共享机制。•静态成员不是某一个类的成员,而是属于整个类;•静态数据成员初始化与一般数据成员初始化有所不同,其初始化格式如下:•类型类名::静态数据成员=初始化值;•静态成员函数可以直接访问该类的静态数据成员,而访问非静态数据成员则可以通过对象进行调用。•采用静态成员函数,可以在创建对象之前处理静态数据成员,这是普通成员函数不能实现的;•静态成员函数不能直接访问类中的非静态成员。如果静态成员函数需要访问非静态成员,需要通过对象名才能访问该对象的非静态数据成员。19友元•功能:提供了不同类或对象的成员函数之间、类的成员函数与普通函数之间进行数据共享的机制。•性质:非对称性(单向的)、非传递性•类的友元函数可以访问类的私有数据成员或保护成员。•友元函数不是类的成员,因而与成员函数存在区别,友元函数不能直接使用对象名,而必须通过对象操作数据成员。•若一个类被声明为另一个类的友元,则该类的所有成员函数都是另一个类的友元。20常类型•指使用关键字const说明的类型,常类型的变量或对象成员的值在程序运行期间是不可改变的。–常引用,如intn=18;constint&b=n;b是一个常引用,它所引用的对象n不允许更改。–常对象,指对象用const限定。常对象的数据成员的值在整个生存期内不能被修改。–常对象成员:由const对对象的成员进行限定。21常对象成员•常成员函数,其说明格式如下:–类型函数名(参数表)const;–const是函数类型的一个组成部分,因此在函数的实现部分也要使用关键字const。–常成员函数不能修改对象的数据成员,也不能调用该类中没有由关键字const修饰的成员函数,从而保证了在常成员函数中不会修改数据成员的值。–const参与区分函数重载。–如果一个对象被说明为常对象,则通过该对象只能调用它的常成员函数。•常数据成员–如果类中说明了常数据成员,构造函数只能通过初始化列表对该数据成员进行初始化,而任何其他函数都不能对该成员赋值。22数组•数据类型表示数组元素值的类型,可以是除void类型以外的任意符合C++规定的数据类型;•数组名表示数组元素在内存中的起始地址;•数组名后必须用方括号,不能用其他括号;•数组元素的数量由常量表达式的值决定,这个值必须在编译时确定;•数组元素的起始标号为0。•数组初始化也可以不用说明数组元素个数,也可只对数组中的部分元素进行初始化。23数组(续)•无论是一维数组还是多维数组,其数组元素在内存中以顺序和连续方式存储,占据一片连续的存储单元;•数组名是常量,表示数组首元素的内存首地址;•如果使用数组名作为函数参数,则实参和形参都应该是数组名,且类型应相同。•使用数组名传递数据时,传递的是数据在内存中的存储地址。•如果在被调用函数中对数组元素的值进行改变,主调函数中实参数组的相应元素值也会相应改变。•对于二维数组,先按行(高维)存储,先存储第一行,然后存储第二行。而每一行内的各元素,则与一维数组相同,按列下标(低维下标)从小到大的顺序存储。24指针•指针定义时所指的数据类型,是指针所指向的数据类型;•指针本身的数据长度由编译系统决定,指针变量本身的值都默认是unsignedlongint型;•定义指针变量必须使用符号“*”,表明它后面的变量是指针变量;•指针变量在未赋初值时不指向任何地址;•一个指针变量只能指向同一类型的变量,不能既指向整型变量又指向实型变量;25“*”和“&”运算符•“*”作为一元运算符出现在定义语句中,在被定义的变量之前时,表示定义的是指针。如int*ptr;•“*”出现在执行语句中获定义语句的初值表达式中作为一元运算符时,表示访问指针所指对象的内容。如cout*p;•“&”出现在变量定义语句中位于被定义变量的左边时,表示定义的是引用。如int&R;•“&”在给变量赋初值时出现在等号右边或在执行语句中作为一元运算符出现时表示取对象的地址。如inta;int*ptr;ptr=&a;26指针运算•指针的算术运算按内存地址的计算规则进行;•指针的算术运算与指针所指向的数据类型具有直接的关系;•指针变量的关系运算指的是指向相同数据类型的指针之间进行的关系运算;•如果两个相同类型的指针相等,就表示这两个指针是指向同一个地址;•不同类型的指针之间,或指针与非0整数之间的关系运算是毫无意义的。27指针的应用•如果被传递的数据是存放在一个连续的内存空间,就可以采用指针作为函数参数,传递大量数据;–形参为指针,实参为数组名和指针;–形参为数组名,实参为数组名和指针;•当一个函数的返回值是指针类型时,这个函数称为指针型函数;–对于指针型函数,通过对存储空间的有效组织,则可以向主调函数返回大量的数据。•指向函数的指针即所定义的指针是专门用于存放函数代码首地址的指针,又称为函数指针。floatmax(floatx,floaty){…}float(*p)(floatx,floaty);p=max;floatc=(*p)(a,b);28公有继承•类的继承方式为public(公有)继承属性;•在派生类中,基类的公有成员和保护成员被继承后其访问属性没有变化,即分别作为派生类的公有成员和保护成员,派生类的成员可以直接访问它们。•但是,在公有继承时派生类的成员无法访问基类的私有成员。29私有继承•在派生类中,基类的公有成员和保护成员作为派生类的私有成员,派生类的成员可以直接访问它们,而派生类的成员无法访问基类的私有成员;•在派生