加载中...
Hello Object 成员版
第1节:初学C++,应该学什么?
第2节:《白话C++》练的什么“功”?
第3节:《白话C++》练的什么“武”?
第4节:打开浏览器,线上玩转C++
第5节:逐字逐句,深入理解C++最小例程
第6节:做一个“会”犯错误的程序员
第7节:Hello World 中文版
第8节:Hello World 函数版
第9节:Hello World 交互版
第10节:Hello World 分支版
第11节:Hello World 循环版
第12节:Hello Object 生死版.上
第13节:Hello Object 生死版. 下
第14节:Hello Object 成员版
第15节:Hello Object 派生版
第16节:Hello Object 多态版
课文封面

当我们设计一个类时,最需要考虑的三件事:

  1. 这一类型的对象,需要拥有哪些属性数据?
  2. 这一类型的对象,它将拥有哪些功能?
  3. 这一类型的对象,它的各个属性和功能之间,有哪些关联关系?

1. 为自定义类型添加成员

是时候来关心对象自身的属性与功能了!在C++中,对象的属性,通常称为“成员数据”,对象的功能,通常称为“成员函数”。

前两节课中,我们还创造过“恐猪”和“恐蛇”物种啊,这两种类型,按说就应该很厉害才是。但可惜,它们只是在类型的名字上,听起来很厉害的样子,其实,我们也只是为它们定制了生和死的功能。

假设我们要写一个游戏程序,里面就有像“恐猪”和“恐蛇”这样的怪兽。游戏的玩家可能需要杀死它们。那么,怪兽是不是要有像血气值、攻击力、防护力这样的数据?同时,除了生和死,怪兽对外要有攻击和被攻击的能力。

攻击的意思就是,玩家进入某一只怪兽的某个范围时,怪兽可能会主动攻击玩家,对玩家造成一定的伤害。被攻击则相反,如果玩家给它一拳,也就是怪兽被攻击了,这时怪兽是直接挂掉?还是说只是血气值减少一丢丢说?或者说给它一拳以后,它反倒更加兴奋了?

血气值,攻击力,防护值 ,它们就是一个类型或者一个对象的属性,通常它们以一种特殊的数据形式出现,称为成员数据。而:怪兽会攻击人也会被攻击,这些就是一个类型或一个对象的能力,通常以特殊的函数形式的出现,称为成员函数,在更多对面向对象的语言,也称为“方法”。

2. 理解方法和属性之间的关系

结合怪兽这个案例,来看看,在定义一个组合类型时,我们需要表达什么?

1、这一类型的对象,需要拥有哪些属性数据?
2、这一类型的对象,它将拥有哪些功能?
3、这一类型的对象,它的各个属性和功能之间,有哪些关联关系?

其中理解第三点,非常重要:属性和功能之间,通常存在紧密的关系。一个功能的实施,可能会引发一些属性值的变化。比如,怪兽被攻击,通常是不是它的血气值 ,也就是游戏中常见的,顶在怪兽头上的“生命条”,会变短;当然,也可以“防护值”这个属性也考虑上,一只怪兽当前的“防护值”越大,比如说它正好穿着铠甲,那么,它被攻击时,血气值一下子减少的数量,通常就慢一些。

再来看“攻击力”这个属性,和“攻击”这个能力的关系——也很好理解 :这只怪兽当前攻击力越强,那么对玩家造成的伤害就越大。

再来看真实一些的例子:赛车。成员数据可以有 油量、速度、方向等等,其成员方法则可以有跑(行驶)、转向、踩油门(也就是加速),踩刹车(也就是减速等等)。大家肯定能够想象得出,汽车的这些成员数据和成员函数之间的合理关系。

如果把汽车的例子进一步简化到只有速度和油量两个数据,以及踩油门和踩刹车两个方法。那么这个赛车类型,用结构/struct的来表达的伪代码,大概就长这样子:

// 伪代码 struct 赛车 { int 速度 = 0; int 油量 = 100; 赛车 () { cout << “赛车启动啦!油量100,速度为零,请踩油门!” << endl; }; void 踩油门() { 加大速度, 消耗油量 }; void 踩刹车() { 降低速度 }; };

基本关系就是,调用一个赛车对象踩油门的方法,车就会加大速度,同时消耗更多的油;而调用踩刹车方法,则会降低速度。

实际定义一个完善的汽车的类型,还是有很多逻辑关系要想清楚的。比如踩油门并不一定会提速,因为汽车可能没油了。

3. 课堂视频

4. 完整示例代码

#include <iostream> // 定义人类结构 struct Person { Person() { std::cout << "哇哇~" << std::endl; }; ~Person() { std::cout << "呜呜~" << std::endl; } // 自我介绍 void Introduce() // 成员函数,方法 { std::cout << "大家好,我叫 " << name << std::endl; } std::string name; // 成员数据,属性 }; int main() { Person xiaoA; xiaoA.name = "小A"; xiaoA.Introduce(); std::cout << "------------------\n"; auto* xiaoB = new Person; // 写法一,取值后再访问成员 (*xiaoB).name = "小B"; (*xiaoB).Introduce(); delete xiaoB; std::cout << "------------------\n"; // 写法二:简易写法“箭头访问符” auto* xiaoC = new Person; xiaoC->name = "小C"; xiaoC->Introduce(); delete xiaoC; }

运行效果:

哇哇~
大家好,我叫 小A
------------------
哇哇~
大家好,我叫 小B
呜呜~
------------------
哇哇~
大家好,我叫 小C
呜呜~
呜呜~