第二十三章类/ class(一)封装 23.1从“我吃饭”开始 23.2从“结构”到“类” 23.3类的成员数据与成员函数 23.3.1成员数据初始化的疑问 23.3.2成员函数的实现 23.4封装 23.4.1私有成员/ private member 23.4.2保护成员/ protected member 23.4.3公有成员/ public member 23.4.4“封装”的作用 23.5作业 23.1从“我吃饭”开始 我吃饭… 其中,“我”是一个变量,“我”的类型是“人类”: “吃”是一个函数。 “饭”也是一个变量,它的类型是“食物”。这里用于做函数“吃”的参数。 “我吃饭”!这是一种面向对象的思想的表达。其中的对象是“我”。以我为中心。我因为 是人类,所以具备“吃”这种能力。如果说“桌子吃饭”,那么编译器会报错,因为桌子属于 家具类,而家具不提供“吃”的函数
第二十三章 类/class (一) 封装 23.1 从“我吃饭”开始 23.2 从“结构”到“类” 23.3 类的成员数据与成员函数 23.3.1 成员数据初始化的疑问 23.3.2 成员函数的实现 23.4 封装 23.4.1 私有成员/private member 23.4.2 保护成员/protected member 23.4.3 公有成员/public member 23.4.4 “封装”的作用 23.5 作业 23.1 从“我吃饭”开始 我吃饭…… 其中,“我”是一个变量,“我”的类型是“人类”; “吃”是一个函数。 “饭”也是一个变量,它的类型是“食物”。这里用于做函数“吃”的参数。 “我吃饭”!这是一种面向对象的思想的表达。其中的对象是“我”。以我为中心。我因为 是人类,所以具备“吃”这种能力。如果说“桌子吃饭”,那么编译器会报错,因为桌子属于 家具类,而家具不提供“吃”的函数
C++是一种具备面向对象能力的编程语言,所以,用C++来表达“我吃饭”这样一件事时, 它的代码风格贴近这种人类的自然语言,即:我.吃(饭):“我”是一个对象,“吃”是“我” 所属对象(人类)的一个函数,而“饭”是函数参数。 换成C语言,因为它不具备面向对象的设计思想,所以,它只能说成:“吃(我,饭)”。 “吃”是函数,“我”和“饭”是两个参数。没有人规则一定要把“我”作为第一个参数,你 尽可写成“吃(饭,我)”。二者比较,面向对象的最基本的好处或许您已经有所体会:自然, 从而不容易出错。 23.2从“结构”到“类” 上一章我们学习了结构( struc t)。(强烈建议你暂时放下新课程,重温一下 struct)。 结构让我们具备了把多种相同或不同的类型,组成一种新类型的能力 比如上一章讲的“宝宝/ Baobao”这一结构,它的组合为 struct baobao char xingMing[1]1;//用字符数组,来存储姓名 int shengao;//身高,整型 float biZhong;//体重,实型 通过 struc t,我们通过将简单数据类型(int, float,bool……)或简单数据类型的数组、 指针,组合成一个新的数据类型。由此,我们在用程序表达复杂的现实世界时,更接近了一步。 但是别忘了,我们说过世界是由“数据”和“动作”组成的。光能定义出各种数据类型,还只 是编程世界的一半。你可能会说,我们有函数啊,函数不是可以表达“动作”? 没错,比如说,宝宝肯定有“吃”的动作,所以我来声明一个“吃”的函数。为了直观,我 们的函数命名为“Chi”。并且我们假充有一种数据类型叫“饭”,同样用拼音Fan表示,首字 母大写,而小写的fan用来做形参
C++是一种具备面向对象能力的编程语言,所以,用 C++来表达“我吃饭”这样一件事时, 它的代码风格贴近这种人类的自然语言,即:我.吃(饭);“我”是一个对象,“吃”是“我” 所属对象(人类)的一个函数,而“饭”是函数参数。 换成 C 语言,因为它不具备面向对象的设计思想,所以,它只能说成:“吃(我,饭)”。 “吃”是函数,“我”和“饭”是两个参数。没有人规则一定要把“我”作为第一个参数,你 尽可写成“吃(饭,我)”。二者比较,面向对象的最基本的好处或许您已经有所体会:自然, 从而不容易出错。 23.2 从“结构”到“类” 上一章我们学习了结构(struct)。(强烈建议你暂时放下新课程,重温一下 struct)。 结构让我们具备了把多种相同或不同的类型,组成一种新类型的能力。 比如上一章讲的“宝宝/BaoBao”这一结构,它的组合为: s t ruct BaoBao { char xingMing[11]; //用字符数组,来存储姓名 int shenGao; //身高,整型 float tiZhong; //体重,实型 } ; 通过 struct,我们通过将简单数据类型(int,float,bool……)或简单数据类型的数组、 指针,组合成一个新的数据类型。由此,我们在用程序表达复杂的现实世界时,更接近了一步。 但是别忘了,我们说过世界是由“数据”和“动作”组成的。光能定义出各种数据类型,还只 是编程世界的一半。你可能会说,我们有函数啊,函数不是可以表达“动作”? 没错,比如说,宝宝肯定有“吃”的动作,所以我来声明一个“吃”的函数。为了直观,我 们的函数命名为“Chi”。并且我们假充有一种数据类型叫“饭”,同样用拼音 Fan 表示,首字 母大写,而小写的 fan 用来做形参
void Chi(Fan fan 乍一看,感觉这个函数这样声明也就对了。“吃饭”函数嘛,有“吃”又有“饭”……可仔 细一想,谁吃饭啊?这个光有吃的动作和吃的东西,和我们前面的“宝宝”数据类型有何关系? 所以,显然不够,需要再加一个参数,用于传一个“要吃饭”的宝宝进去。因此函数变成 void Chi(BaoBao bb, Fan fan) 得,“吃我饭”的表达出来了。过程化的编程,其设计重在关心“过程”,比如:“如何吃”, 但这个世界要求我们完整地关心“谁?如何吃?吃什么?”。事实上,同一样一个“吃”,宝 宝吃的动作,和一个大男人吃的动作;或者,吃饭还是吃奶的动作?怕是完全不一样。如果真 写,就不得不写很多版本的“吃”这一函数 假设用DNR表大男人(晕,好像大女人也可以?): void dnrchi( dnR dnr, PingGuo pg);//吃函数版本一:大男人吃苹果 void dnrchi( dnr dnr, Fan fan);//吃函数版本二:大男人吃饭 void baobaochi( Baobao bb, Nai nai);//吃函数版本三:宝宝吃奶 void baobaochi( Baobao bb, Fan fan);//吃函数版本四:宝宝吃饭 这样的函数还可以有很多。函数多或许并没有错,必竟所要表达事物本来就复杂。然而问题 是我们如何去理解,区分,记忆这些函数呢?仅靠函数名和函数参数的不同吗?在超市付款时 看过收款员拉开过放钱的小抽屉吗?拉开一看,都是钱,但10元的5元,100元的及硬币分门 别类地放好……聪明的你一定会提出:如果能把函数也归类就好了……这就有了“类”,英文 称为: class 请仔细看,下面示例的 class定义里,加入了一个函数: class baobao
void Chi(Fan fan); 乍一看,感觉这个函数这样声明也就对了。“吃饭”函数嘛,有“吃”又有“饭”……可仔 细一想,谁吃饭啊?这个光有吃的动作和吃的东西,和我们前面的“宝宝”数据类型有何关系? 所以,显然不够,需要再加一个参数,用于传一个“要吃饭”的宝宝进去。因此函数变成: void Chi(BaoBao bb, Fan fan); 得,“吃我饭”的表达出来了。过程化的编程,其设计重在关心“过程”,比如:“如何吃”, 但这个世界要求我们完整地关心“谁?如何吃?吃什么?”。事实上,同一样一个“吃”,宝 宝吃的动作,和一个大男人吃的动作;或者,吃饭还是吃奶的动作?怕是完全不一样。如果真 写,就不得不写很多版本的“吃”这一函数: 假设用 DNR 表大男人(晕,好像大女人也可以?): void DNRChi(DNR dnr, PingGuo pg); //吃函数版本一:大男人吃苹果 void DNRChi(DNR dnr,Fan fan); //吃函数版本二:大男人吃饭 void BaoBaoChi(BaoBao bb, Nai nai); //吃函数版本三:宝宝吃奶 void BaoBaoChi(BaoBao bb, Fan fan); //吃函数版本四:宝宝吃饭 ...... 这样的函数还可以有很多。函数多或许并没有错,必竟所要表达事物本来就复杂。然而问题 是我们如何去理解,区分,记忆这些函数呢?仅靠函数名和函数参数的不同吗?在超市付款时, 看过收款员拉开过放钱的小抽屉吗?拉开一看,都是钱,但 10 元的 5 元,100 元的及硬币分门 别类地放好……聪明的你一定会提出:如果能把函数也归类就好了……这就有了“类”,英文 称为:class。 请仔细看,下面示例的 class 定义里,加入了一个函数: class BaoBao
char xingMing[11];//用字符数组,来存储姓名 int shengao;//身高,整型 float tazhong;∥/体重,实型 void chi( Fan fan);//加入“吃”的函数。 这算是一个“突变”一一我们一直说着的“动作”与“数据”从这里开始合二为一,表面看 来或许不过如此:无非是在类的定义里,同时可以包括数据及函数。然而却由此开启了“面向 对象”世界之门。如果你喜欢武侠,那你可以把它看成一门语言打通了任督二脉… 类的数据定义里,出现函数,那么,这个函数的声明它占用类的大小吗? 来看两个数据定义,前者是 struct,后者是 class前者没有包括函数,后者包括一个函数。 其余的数据定义完全一样。 lass bAobao truct S Baobao char xingMing[lll char xingMing[ll] int shenGao void Chi(inta);//参数可不能 用Fan了 然后,我们来做个比较
{ char xingMing[11]; //用字符数组,来存储姓名 int shenGao; //身高,整型 float tiZhong; //体重,实型 void Chi(Fan fan); //加入“吃”的函数。 }; 这算是一个“突变”——我们一直说着的“动作”与“数据”从这里开始合二为一,表面看 来或许不过如此:无非是在类的定义里,同时可以包括数据及函数。然而却由此开启了“面向 对象”世界之门。如果你喜欢武侠,那你可以把它看成一门语言打通了任督二脉…… 类的数据定义里,出现函数,那么,这个函数的声明它占用类的大小吗? 来看两个数据定义,前者是 struct,后者是 class。前者没有包括函数,后者包括一个函数。 其余的数据定义完全一样。 struct SBaoBao { char xingMing[11]; int shenGao; float tiZhou; }; class CBaoBao { char xingMing[11]; int shenGao; float tiZhou; void Chi(int a); //参数可不能 用 Fan 了 }; 然后,我们来做个比较:
[略] 23.3类的成员数据与成员函数 成员?长这么大,肯定填写过什么“家庭成员”的样的表格。我们进行的数据定义或函数定 义,它们之所以前面有没加个“成员”的修饰,是因为它们都没有一个家,哎,谁不想有个家 呢?在C#和Java里,所有数据及函数都必须有个家才可以存在,而在C+里,允许数据或函数 可以没有家(不属于某个类):也可以允许有个家(属于某个类)。 //下面就是 CAocao类的成员数据 char xingMing[11] int shengao float tizhe //而这个是 CAobao类的成员函数 void Chi(int a 类的成员数据和成员函数,都称为类的成员(像是一句废话? 23.3.1成员数据初始化的疑问 我们以前常有这样的代码: inta=100;//定义一个变量,同时给它赋值为100
[略] 23.3 类的成员数据与成员函数 成员?长这么大,肯定填写过什么“家庭成员”的样的表格。我们进行的数据定义或函数定 义,它们之所以前面有没加个“成员”的修饰,是因为它们都没有一个家,哎,谁不想有个家 呢?在 C#和 Java 里,所有数据及函数都必须有个家才可以存在,而在 C++里,允许数据或函数 可以没有家(不属于某个类);也可以允许有个家(属于某个类)。 class CBaoBao { //下面就是 CBaoCBao 类的成员数据: char xingMing[11]; int shenGao; float tiZhou; //而这个是 CBaoBao 类的成员函数: void Chi(int a); }; 类的成员数据和成员函数,都称为类的成员(像是一句废话?)。 23.3.1 成员数据初始化的疑问 我们以前常有这样的代码: int a = 100; //定义一个变量,同时给它赋值为 100