递归的基本思想:问题层层分解
递归的关键在于找出递归定义和递归终止条件
递归定义:使问题向边界条件转化的规则。递归定义必须能使问题越来越简单。
递归终止条件:也就是所描述问题的最简单情况,它本身不再使用递归的定义。
递归算法解题通常有三个步骤:
1)分析问题、寻找递归:找出大规模问题与小规模问题的关系,这样通过递归使问题的规模逐渐变小。
2)设置边界、控制递归:找出停止条件。
3)设计函数、确定参数:设计函数体中的操作及相关参数。
结构体
使用结构体,必须要先声明一个结构体类型,再定义和使用结构体变量。
定义结构体变量格式如下:
也可以把结构体类型声明和变量定义合在一起,格式如下:
结构体的使用:(使用过程中通过成员对它使用)
结构体变量具有以下特点:
(1)可以对结构体变量的整体进行操作。
例如:swap(a[i],a[j])
(2)可以对结构体变量的成员进行操作。
引用结构体变量中成员的格式为:
结构体变量名. 成员名
(3)结构体变量的初始化方法与数组类似。
标准库string类
头文件:#include 〈string〉使用string 类要包含头文件 不能加.h,针对字符数组的才是
字符串变量和普通变量无太大区别,唯一区别就是加法运算是首尾连接
(1) getline()函数 (遇回车时结束)
两个参数:输入流对象和存放读入字符串的string对象
从指定输入流中读取内容,遇到换行符为止;将所读内容存入指定的string对象中,流中的换行符被读取并丢弃//每次读取一行文本,直到文件结束
返回参数输入流对象
(2)size()函数返回string对象的长度,即对象中字符的个数
返回的长度是string::size_type类型
使用标准库中iostream可以读写string对象
c语言的输入输出%s对字符串变量不起作用
键盘输入时遇空格结束,不能有分隔符
指针
定义指针变量的语法:类型 *指针变量;
使用指针的注意事项
定义指针时,应该对指针进行初始化
指针的运算
同类型的指针可以进行相等(==)或不相等(!=)的比较操作,比较的结果是布尔类型
指针可以进行加或减整数值的算术运算
自增、自减运算适用于指向数组元素的指针
C++通过new和delete运算符进行动态存储空间的管理
new表达式的三种形式
<1>.分配单个对象:new 类型 或者 new 类型(初始值)
<2>.分配多个连续存储的对象:new 类型[数组大小]
<3>.定位new,在指定位置分配空间:new (指针) 类型;
必须包含标准库头文件
delete运算符
释放new分配的单个对象 delete 指针;
释放new分配的数组 delete[] 指针;
定位new没有对应的delete表达式
const限定指针
1.指向const对象的指针(非const )
cp是指向常量的指针,它所指向的内存中的内容不可以改变,即的值不能改变
2.指向非const对象的const指针
cp是常量指针,初始化后值不能改变,指向固定的单元
3.指向const对象的const指针
引用
引用的定义和初始化
类型 &引用名 = 初始值;
使用指针访问数组时需要控制指针的范围,确保指针指向数组的元素
类与对象
类
1)构造函数(有参无参)
2)get/set函数(对私有成员操作的公有函数)
3)析构函数
C++类定义的格式:(分号不能省略 )
注意事项
● 类的数据成员可以是其他类的对象,但不能以类自身的对 象作为本类的成员,而类自身的指针和引用可以作为类的成员。
●类定义必须以分号“;”结束。
●类与结构体的区别:
没有明确指定类成员的访问权限时,C++结构体的成员是公有的,而类的成员是私有的。
●private只能在类内使用,(更安全)
●一般实现功能的成员函数都是公有的,数据成员是私有的
●类名的第一个字母要大写,有些在类名前加大写的C
类的起名要望文知意
●类的数据成员可以是其他类的对象
成员函数可以操作的数据
●本类的数据成员
●函数内定义的局部变量
●全局变量(不好,在面向对象里不建议使用)
类的成员函数通过操作数据成员来实现功能
成员函数加不加形参问题:
如果操作需要从外界引入数据 加形参;如果只对数据成员操作 不加形参
对象
对象成员的访问包括:
●圆点访问形式:对象名.公有成员
●指针访问形式: 对象指针变量名->公有成员
函数重载:函数名相同,但参数不相同(类型不同,或者个数不同)的一组函数。
默认构造函数
如果类中没有定义构造函数,系统将自动生成一个默认形式的构造函数,用于创建对象,默认构造函数形式:
类名::类名(){}
通常,利用构造函数创建对象有以下两种方法:
(1) 利用构造函数直接创建对象.其一般形式为:
类名 对象名[(实参表)];
不带参数:当用户没定义构造函数时,调用默认的构造函数;当用户定义了构造函数时,调用无参的构造函数(没有无参构造函数时要出错!系统不会调用默认构造函数)
带实参表:系统按照重载函数匹配原则,调用对应的构造函数;
利用构造函数创建对象时,通过指针和new来实现。其一般语法形式为:
类名 *指针变量 = new 类名[(实参表)];
构造函数一定重载
●创建对象时一定要按照构造函数定义的形式创建,参数和类型不匹配的方式不正确
●要创建构造函数就一定要构造一个无参的构造函数
定义构造函数至少写俩
构造函数的初始化列表
--------数据成员的初始化
构造函数初始化成员有两种方法:
● A.使用构造函数的函数体进行初始化
B.使用构造函数的初始化列表进行初始化
funname(参数列表):初始化列表
{ 函数体,可以是空函数体 }
初始化列表的形式:
成员名1(形参名1),成员名2(形参名2),成员名n(形参名n)
必须使用参数初始化列表对数据成员进行初始化的几种情况
1.数据成员为常量
2.数据成员为引用类型
3.数据成员为没有无参构造函数的类的对象
类成员的初始化的顺序:
按照数据成员在类中的声明顺序进行初始化,与初始化成员列表中出现的顺序无关
使用this指针的三种情况
1)在类的非静态成员函数中返回类对象本身或对象的引用的时候,直接使用 return *this,返回本对象的地址时,return this。
2)当参数与成员变量名相同时,如this->x = x,不能写成x = x。
3)避免对同一对象进行赋值操作,判断两个对象是否相同时,使用this指针。
复制构造函数
语法形式:类名 :: 类名(const 类名 & 引用名 , …);
特点:
1.复制构造函数名与类名相同,并且也没有返回值类型。
2.复制构造函数可写在类中,也可以写在类外。
3.复制构造函数要求有一个类类型的引用参数。
4.如果没有显式定义复制构造函数,系统自动生成一个默认形式的复制构造函数。
使用情况:
用赋值语句
对象是函数返回值时
当对象作为一个函数实参传递给函数的形参时
关于浅复制:
●在用一个对象初始化另一个对象时,只复制了数据成员,而没有复制资源,使两个对象同时指向了同一资源的复制方式称为浅复制。
即:对于复杂类型的数据成员只复制了存储地址而没有复制存储内容
●默认复制构造函数所进行的是简单数据复制,即浅复制
关于深复制:
●通过一个对象初始化另一个对象时,不仅复制了数据成员,也复制了资源的复制方式称为深复制。
●自定义复制构造函数所进行的复制是浅复制。
深复制构造函数必须显式定义
深复制构造函数的特点
定义:类名::类名([const] 类名 &对象名);
成员变量的处理:对复杂类型的成员变量,使用new操作符进行空间的申请,然后进行相关的复制操作
类的其他成员
常成员
在类的成员函数说明后面可以加const关键字,则该成员函数成为常量成员函数
const放在最前面,返回值为常量;
放在最后面,才为常成员函数;
常对象
如果在说明对象时用const修饰,则被说明的对象为常对象。
常对象的说明形式如下:类名 const 对象名[(参数表)];
或者const 类名 对象名[(参数表)];
在定义常对象时必须进行初始化,而且不能被更新。
说明:
(1)C++不允许直接或间接更改常对象的数据成员。
(2)C++规定常对象只能调用它的常成员函数、静态成员函数、构造函数(具有公有访问权限)。
常成员函数
类型说明符 函数名(参数表) const;
const是函数类型的一个组成部分,因此在函数的实现部分也要带关键字const。
常成员函数不能更新对象的数据,也不能调用非const修饰的成员函数(静态成员函数、构造函数除外)
静态成员
类成员冠以static声明时,称为静态成员。
静态数据成员为同类对象共享。
静态成员函数与静态数据成员协同操作。
定义静态成员函数的格式如下:
static 返回类型 静态成员函数名(参数表);
与静态数据成员类似,调用公有静态成员函数的一般格式:
类名::静态成员函数名(实参表)
对象. 静态成员函数名(实参表)
对象指针->静态成员函数名(实参表)
在类外进行静态数据成员的声明
类型 类名::静态数据成员[=初始化值]; //必须进行声明
不能在成员初始化列表中进行初始化
静态函数仅可以访问静态成员,或是静态成员函数或是静态数据成员。
友元函数(不建议使用)
只在重载输入输出时使用,其他情况不能使用
用于左右操作数类型不同的情况
将成员函数声明为友元函数。
当第一个操作数不是当前对象时,引入新重载方法。
友元函数不能重载
形参是复杂类型时,使用引用方式传参,传参数是为了使用,不是修改操作数。
两个类定义顺序不可颠倒
友元类 (不建议使用,破坏类的封闭性)
friend class 类名;
运算符重载
重载运算符的限制:
不改变运算符的优先级
不改变运算符的结合性
不改变运算符所需要的操作数
不能创建新的运算符
运算符函数可以重载为成员函数或友元函数
一元运算符
重载为成员函数,解释为:
操作数由对象Object通过this指针隐含传递
重载为友元函数,解释为:
操作数由参数表的参数Object提供
二元运算符
重载为成员函数,解释为:
左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递
重载为友元函数,解释为:
左右操作数都由参数传递
用成员函数重载运算符
成员运算符函数的原型在类的内部声明格式如下:
双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数
用友元函数重载
在第一个参数需要隐式转换的情形下,使用友元函数重载运算符是正确的选择
友元函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
C++中不能用友元函数重载的运算符有 = () [] ->
成员运算符函数与友元运算符函数的比较
主要区别在于操作数据个数不同
(1) 成员运算符函数比友元运算符函数少带一个参数(后置的++、–需要增加一个形参)。
(2) 双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。
重载赋值运算符
赋值运算符重载用于对象数据的复制
operator= 必须重载为成员函数
重载函数原型为:
例 定义Name类的重载赋值函数
重载运算符[]和()
运算符 [] 和 () 是二元运算符
[] 和 () 只能用成员函数重载,不能用友元函数重载
重载下标运算符[]
运算符用于访问数据对象的元素
重载格式
重载函数调用符 ()
重载输入输出流可以增加判断性语句,来对数据进行合法性检测
重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)
定义输入运算符函数 “>>”重载函数
管理信息系统开发基本步骤
1.了解系统要实现什么功能?
2.对系统功能进行分类汇总
3.设计操作类
一个成员函数实现一个具体功能;
设确定数据成员,设计构造函数;
4.设计数据类
整合操作类所需要的数据、设计数据类
5.明确如何修饰数据成员、确定数据类的成员函数
6.编码调试数据类
在main函数中创建数据类对象、调用各成员函数
7.调试操作类
先调试最急需的成员函数;
再陆续增加成员函数
设计多组测试数据,用不同的测试数据反复运行程序