大家好,在这一小节中,我们通过一个具体的例子
来看一看如何从一个客观事物抽现出一个c++类来。
那么这个例题呢,是要求写一个程序
通过输入矩形的宽和高,来输出面积和相应的周长。
那么我们都知道说,对于一个矩形而言,如果
给定了相应的宽和高,那么这个矩形就被定义下来了。
同时呢,又可以去计算这个矩形的面积和周长。
那么对于这样的一个程序设计题目来讲的话呢,这个
矩形它拥有两个属性,也就是所谓的宽和高。
那么我们可以通过去设置两个变量来分别代表宽和高,
此外呢,对于矩形还有这样的相应的操作,分别是去设置宽和高,
去计算面积以及去计算周长。
那么这样相应的对应的操作呢,在具体程序设计的时候就可以实现为三个对应的函数,
我们来具体看一看这样的两个属性
三个操作会怎么样能够被抽象为一个类呢?
我们可以首先呢去对应定义在代码中间的这样的几个变量和函数,
我们可以呢通过去设置int型的w和h
去代表这个矩形的宽和高。
那么有了这样两个变量之后呢,我们可以去构建这样三个函数,
分别呢去计算面积,计算周长和初始化,
那么来去对这个矩形进行一定的操作。
那么有了这样的一个分析之后呢,我们就可以把这样一系列属性和操作封装起来,
形成一个称为叫做矩形类。
那么这个矩形类呢,中间的w和h这样两个 变量呢,我们把它称之为叫做成员变量。
而对应的这样三个函数,去计算周长、面积和设置宽高
那么可以认为说呢叫做类的成员函数。
而成员变量和成员函数呢又通称为叫做类的成员。
那么我们就会发现说,其实这个类挺似曾相识的。不错,
我们可以看到呢,其实类就是一个包含了函数的结构体。
那么有了这样的一个非常直观的和似曾相识的概念之后呢,
我们来看一看在c++代码中间是如何去实现这样的一个矩形类的。
那么对于 这个类呢,我们首先使用class
这样的一个关键字去声明说,啊我要进行一个类定义。
那么class之后呢就是我们自己命名的这样的一个类名,我们把它称之为叫做CRectangle。
那么CRectangle之后呢,它定义了一对大的花括号,
在这个花括号内部呢,就是整个类定义。
注意了,每一个类的结束呢都必须有分号来表帧。
那么在这个类定义中间呢,我们看到了它呢首先会定义
两个变量,分别是表帧了矩形的宽和高。
之后呢,又定义了这样三个函数,
这三个函数呢,分别是对矩形的一些操作,
那么有初始化的,init, 有去计算面积的area,有去计算周长的perimeter。
那么有了这样三个函数之后呢,就可以对整个矩形有一个比较充分的 行为的一个描述。
那么这样的话呢,其实就是简单定义的这样一个叫做CRectangle的一个class。
那么注意呢,就是我们在这里面还有一个对于访问范围的一个
说明符,这个说明符呢我们会在后续的课程呢进一步地去讲解。
有了这样的一个CRectangle类之后,那怎么用呢?我们可以在
main函数里头除了去定义宽高这些
变量去用来呢后续的输入
这个对应的参数之外呢,我们还可以使用CRectangle类
来去声明一个新的
变量称为r。那么这个r呢,实际上就是CRectangle类的一个对象。
这个对象呢,有了之后,我们就可以
利用这个对象去访问它的成员函数。
那么可以通过r的init函数
去初始化我们从键盘输入的宽和高,
w和h。那么有了相应这个r矩形的宽和高之后呢,
我们就可以去计算相应的r的面积和r的周长,
然后把它输出出来,这样呢就满足了整个例题的需要。
我们看到了说,其实呢,CRectangle实际上是一个
特殊的类型。这个类型呢,是你自己以类的形式来定义的。
它其实就和我们之前看到的这些int,flout
没有什么太大的区别,只是一个比较复杂的、带有函数的这样的一个类型。
那么这个类型的变量呢,我们把它称为类的实例,
也称为呢叫做对象。 而这个过程,定义这个类定义的
变量的过程呢,我们把它称之为叫做实例化。 那么这实际上呢就是一个最基本的
类定义和类实例化生成对象的一个过程。
当我们看到说对于每一个类对应的
对象而言呢,它自身实际上是有内存空间分配的。
每一个对象呢都有各自的空间,比方说我们刚才的这个CRectangle而言,
那么每一个对象的大小等于什么呢?对象的大小
就等于所有成员变量的大小之和,
那么以CRectangle类的对象为例,那么它
在内存空间里头开辟一块地方出来,它要有多大呢?
那么它实际上就是两个int型的大小, 所以如果这时候你sizeof一下
CRectangle的话你会发现它等于8,就是两个int。
那么除此之外呢要注意就是,在内存中间,如果你有两个对象,
分别是r1和r2的话,那么这两个
CRectangle的对象呢,它们之间是有各自的空间的,
不会相互影响。如果r1中间的一个变量呢
发生了变化,是不会影响到r2自身的 对象中间的成员的。
此外的话呢,对象之间呢我们是可以使用等号来进行赋值的,
但是呢,注意不能使用这些符号来进行比较。
不过其实c++本身语言呢实际上是给大家留了一个空间的,
那就是后面呢我们会给大家介绍说运算符重载之后
我们就可以使用这些符号来进行对象之间的比较了。
那么在知道了类和对象之后,我们就来
重点看一下说如何去访问类的成员变量和成员函数,对吧?
我们定义CRectangle在这个类里面,定义了一系列的变量和函数,
但具体怎么在它的实例化对象中间去访问呢?
访问的第一种方法就是我们使用对象名加一点,加成员名,
那么我们利用CRectangle这样的一个类去实例化定义了两个
对象分别是r1和r2,
那么我们需要去访问r1的某一个成员变量
w的时候,我们就可以使用r1.w,
就可以直接进行赋值了,对吧?我们把5赋给
r1这个对象里面的这个w,具体w这个成员变量
那么我们也可以同样去对r2这样的一个对象进行操作,
那么这一次呢我们不需要通过成员变量了,我们希望利用成员函数
来进行访问,所以呢我们可以利用r2.init
这样的一个函数去把3和4分别设置给r2的
这个w和h。 那么注意了,r1和r2我们在刚刚讲过,
它们彼此之间呢在内存中间是相互独立的
两块空间。
那么对r1而言呢,我们一开始进行了赋值之后w就变成了5。
而r2.init这样的一个函数调用呢。只会把r2的w
初始化为3,h呢初始化为4,它
不会影响到r1中间的任何一个成员变量的值。
第二种方法呢,我们同样可以使用指针来进行访问。
我们可以利用指针指向其中的一个成员名
来进行具体的这个访问成员变量和成员函数的操作。
同样的,我们用CRectangle呢去定义两个对象,r1和r2,
之后呢,我们可以用CRectangle类型呢去定义一个指针*p1和*p2,
分别指向r1和r2这两个对象的首地址。
之后呢,我们就可以用p1和p2来指向
对应的w和Init函数。
那么同样的利用指针,也是分别作用在自身的对象上。
最后一种呢,就是使用引用。 引用呢,我们之前在郭老师的这个
小节介绍中间呢已经具体学习了引用这样的一种方法,那么其实说白了呢
一句话,引用就是某一个成员变量的一个别名,
那么第三种方法去访问成员变量呢,就可以利用引用名 加一点,加成员名来进行访问。
那么还是这样的一个CRectangle的例子。
我们去对应实例化的一个对象r2,那么我们要利用一个引用,
rr作为r2的一个别名,
那么我们除了用r2进行一点访问之外呢,
我们也可以使用rr.,来分别访问w和Init, 注意呢,
在这个在内存空间中,r2呢同时也可以认为是rr,
所以呢,我们利用rr的这个w呢,先初始化为5之后,
如果我们再次调用Init这个成员函数的话,那么这块的
对应的成员变量呢,就被修改为3,
那么h呢就修改为4,因为我们说呢,r2的值
和rtwo的值呢实际上是一回事。
那么最后呢,我们来看一下说
除了刚才main函数里头我们利用直接利用这个
r.Area和r.Perimeter呢,可以进行输出,同样呢,
我们也可以去写一个叫做PointRectangle这样的函数
来表示 利用函数来输出这个结果。那么这个函数的话呢,
就需要利用CRectangle的这样的一个对象
来作为参数呢进行传递。
也就是说,我们利用CRectangle呢,定义了一个对象r3,我们对r3呢
进行了初始化的设置,调用了它的Init函数3和4,
我们需要打印输出周长和面积的时候呢,我们可以把r3
作为参数传进来,那么传进来之后呢, 调用PointRectangle这样
的一个具体的函数,那么这个函数里面呢,它cout是谁呢? cout实际上是r3的Area这样的一个函数,
以及r3的
P这样的一个函数。那么就可以对应
输出r3这个对象的面积和周长了。
那么它其实跟我们之前传统意义上的参数呢
是一模一样的,只不过这个参数的类型呢是CRectangle。
最后呢,我们来看一下,除了之前我们把类的
成员函数的定义写在类的这个
定义中间呢,我们还可以把成员函数呢 分离出来,只在类定义里面呢去
声明我的这个类里面呢包含了这一系列的这个
成员函数。那么具体的这个函数的定义呢,可以防止整个类定义的之外,
那么在类定义之外呢,怎么样去区分这个函数本身是成员函数
而不是一个普通意义上的函数呢?我们可以利用CRectangle::
这样的一个标记去声明说, 哎,我这三个函数它不是
普通意义上的函数,它是属于CRectangle类的。
那么有了这样的三个,有了这样的标记之后呢,
这样三个函数就可以作为类的成员函数
来进行定义了。那么大家注意,同样的,在调用这些类的成员函数的时候,
我们仍然需要使用对象。对象的指针,
或者是对象的引用来进行,它也不能作为普通函数来进行访问。