一、类和对象
1,面向过程程序设计(自顶向下设计)
分析出解决问题所需的步骤,然后用函数把这些步骤一一实现,使用的时候一个一个调用
过程式设计对于比较复杂的问题,或是在开发中需求变化比较多的时候,往往显示力不从心
· 这是因为过程式的设计是自上而下的,这要求设计者在一开始就要对需要解决的问题有一定的了解。在问题比较复杂的社会,要做到做一点会比较困难。
· 开发一个系统的过程往往也是一个对系统不断了解和学习的过程,而过程式的设计方法忽略了这一点。
· 过程式设计使用函数定义操作;使用变量定义事物的属性、特征;这样做的结果是数据和操作被分离。
· 比如go()函数表示汽车前进,而汽车的排量、燃料种类等等都是和go()函数分离的。
· 数据和操作被分离,容易导致对一种数据的操作分布在整个数据的各个角落,从而造成系统维护困难。系统越大情况越糟糕。
2,面向对象程序设计
· 面向对象从问题的一部分入手,把构成问题的事物分解成许多对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物自身及其在整个解决问题的过程中的行为。
· C++语言中,对象抽象成类,类成为模块化元素,是划分程序的基本单位。
· 类将对象的数据和操作(成员函数)封装在一起,可以说这就是对象设计方法最基本的特征。
问题:
现在将一批鸭子用若干个盒子包装起来。将这一过程用程序表现出来。
面向过程的设计方法:
涉及到三个操作,对应三个函数:
①open() 把盒子打开,目标是得到打开的盒子
②put()把鸭子装进去,目标是得到里面装着鸭子的盒子
③close()把盒子盖好,目标是获得盖好盒盖的有鸭子的盒子
定义问题中的数据:
用数字state[]表示盒子的状态,state[k]表示第k个盒子的情况。可将盒子状态分为4种情况(用0-3表示):
0-----未开盖的空盒
1------开盖的空盒
2-------装好鸭子、未盖好盖子的盒子
3-------装好鸭子并盖好盖子的盒子
用duckState[] 表示鸭子的状态,duckState[n]表示第n只鸭子的情况。
鸭子的状态是未被装入和已被装入两种,因此可以用bool类型数组表示。
int open(int state[],int k)打开第k个盒子,成功返回编号,失败返回-1
int put(int state[],int k,bool duckState[],n)将第n只鸭子放入第k个盒子,成功则返回盒子编号,失败返回-1
void close(int state[],int k)将第k个盒子盖好
至此,三个步骤都用函数实现了,感觉还行,下面我们看看面向对象的方法
面向对象的分析设计方式
面向对象的方法不是从“怎么做”出发,而是从“是什么”出发考虑问题。首先寻找问题中的对象。为了发现对象,要在系统说明的文档中查找名词。
在问题中,我们可以找到重要的名词:盒子,鸭子
然后将这些对象的共有特性以及其责任抽象称为特殊的数据类型------类
在C++中,类用class定义
考察盒子对象,显然“状态”是盒子的属性,可以把“将鸭子放入盒子中”归纳为盒子的任务。
为了完成把鸭子装进盒子的任务,需要做三个动作:
打开盖子,装入,合上盖子。每个导致对应类的一个成员函数。
这样一来,我们要做的是对某个盒子发出指令:
①k号盒子,请把盖子打开
②k号盒子,请把第n只鸭子放入
③k号盒子,请把盖子盖上
每个指令计算调用一个成员函数。
盒子类可定义如下:
class BOX{int ID; //盒子编号,为什么不是数组?int state; //盒子状态,为什么不是数组?int open(); //打开盒子,为什么没有参数?int put(bool duckState[],n); //将第n只放入盒子void close(); //将盖子盖好,为什么没有参数?
}
放入物品的过程中盒子b[k]应当执行如下代码:
b[k].open()
b[k].put(duckState,n);
b[k].close()
· 在面向过程的方法中,数据和函数是分离的,数据可能散落在程序的各个角落,不易维护;
而面向对象的方法中,函数和数据结合在一起,每个对象都有自己独立的数据,含义清晰,易于维护。
· 在面向过程方法过程中,需要在开始阶段就分析清楚每个过程的作用,并编写合适的函数,一旦在后续工作中发现初始的分析不恰当,则可能改动很大;而面向对象的设计方法允许开发者从问题的局部开始,先找出类,在找出类之间的关系,在开发过程中逐步加深对系统的理解
如何声明一个类
class 类名 // class是声明类的关键字
{
private:
//私有成员数据(属性)和私有成员函数(方法)
protected:
//保护成员数据(属性)和保护成员函数(方法)
public:
//公有成员数据(属性)和公有成员函数(方法)
};
//花括号内部分是类体。类声明以分号结尾。
声明一个银行账户类
class Account
{
public: // 公有成员int ID // 账户IDchar Name[20]; //姓名float balance; //余额int withdraw(float m) //取出数量为m的钱{if(balance > m){balance = balance - m; return 1;}else return -1;}void deposits(float m);
};
void Account::deposits(float m){ //在类内部或外部实现函数都可balance = balance + m;
}
声明具体对象或对象数组
正如“人”是抽象的定义,生活的舞台都是具体等等张三,李四在表演;
“账户”类也是抽象的,只有定义了具体账户,才能执行某些操作。
定义一个账户对象:
Account my Account;
而下面语句则定义了包含10个对象的数组:
Account account[10]
不论是定义一个对象,还是一组对象,C++都会在内存中为每一个对象分配必要的空间
公有函数的使用方法
格式:
对象名.函数名(实际参数)
比如,要向myAccount存入600元,格式如下:
myAccount.deposit(600.0)
注意:仅仅对公有函数可以这样使用
类对象的公有变量也直接修改或显示。比如:
myAccount.ID = 10001; //设定账户ID
同类对象之间可以赋值比如下面的语句:
myAccount = account[0];
· 类也可以作为一个函数的参数或返回值出现,下面定义一个不属于任何类的函数:
//从账户A转m元到账户B
bool transfer(Account A , Account B, float m){if(A.withdraw(m) == 1){ //若A取款成功B.deposits(m); //向B存款return true;}else return false;
}
注意:调用函数:
transfer(myAccount,account[0],1000.0);
不会修改myAccount和account[0]对象的数值!
原理:
· 虽然函数中A和B出现在参数中,不是在transfer函数体内定义,但A和B仍是此函数内部的局部变量
· 对象myAccount和account[0]分别赋值给A和B(值传递)。这里myAccount和account[0]都是彼此独立的对象
· 在函数中从账户A转m元到账户B。但是myAccount和account[0]对象无任何变化
· 函数transfer执行完毕后,其中的局部变量A和B也随之消失。
解决本问题需要利用指针或引用