类和对象的基本概念

在C++中,用户定义类型指的就是实现抽象接口的类设计。
在谈类之前,我们先谈谈接口。

一、接口

1.什么是接口

要使用一个类,必须了解其公共接口。要编写一个类,必须创建其公共接口。
在书上说接口是一个共享框架。其实接口可以简单的认为就是一个供用户使用的方法。举例子简单点可以认为,一个.cpp文件实现了一个功能(这个功能可能还可以分成多个小功能,在文件内被实现,所以文件内可能有多个函数相互调用配合)。然后头文件只声明一个或着其中几个函数,我们调用这些函数就可以完全使用这些功能。那么这几个函数就是接口,供我们调用。我们这时候不需要具体知道文件里那些函数怎么实现怎么做的,我们只需要知道给的这几个函数(接口)怎么调用,实现什么功能就好了。
所以接口其实也是封装的产物。将大大小小的函数封装到一起实现一个功能,给几个函数(接口)供外部调用就可以使用这个文件的功能。文件也可以是类等等封装函数的东西。

2.设计接口的原则

(1)单一性(也可以称为单一职责原则)。
单一性是指接口做的事情应该是比较单一的事情,比如登录接口,单纯的读取用户输入信息,返回用户信息即可。在登陆页面用户只担心能否登陆上,我们没必要返回其他无用信息给用户,用户登录不上就返回登录失败,用户登录上就跳转到其他页面即可。
(2)可扩展性。
接口可扩展。其实每个接口内部可能有其他小接口。比如一个信息页面,跳转到这个页面是一个接口,在这个页面查看信息又是一个一个小接口,比如查看成绩,查看课表,这些也可以看作是一个一个接口。跳转到这个页面的选项,也是一个接口,这整个页面必须是可扩展的,比如我们需要添加教室课表查询,我们只需要将教师课表查询用一个接口完成跳转就好,要插入一个教师课表查询就把这个跳转接口插入到这个页面就好,其他接口什么的都不用更改。
(3)接口隔离原则
建立单一接口,接口与接口之间尽量不要有较大联系。
等等,还有其他接口原则,但是主要也都能归咎于这些上面。其实类的设计原则和接口原则差不多,类也可以设计成一个接口,一个类完成一个功能,对外暴露一个方法作为接口。我们将一个大功能分成一个个小功能,每个小功能用一个类来完成,类对外提供一个接口,小的看,类对外提供的成员函数是一个接口,往大一点看,其实这些类就是实现一个个小功能的接口。

三.类

1.类的基本概念

类是一种将抽象转化为用户定义类型的工具。它将数据的表示和操纵组合成一个包,也可以说封装成一个包。
类的数据一般都设计成私有。接口设计成公有,对外公开,其他在内部实现功能的,不需要外部调用,默默的在类内部工作的成员函数就不需要对外公开。这些设置与私有、保护、公有有关。

2.类的基本作用

将数据和操纵包装成包。简单说,就是起封装作用。将一些数据和对数据的操纵封装成包,或者将一个小功能的实现封装成包。

3.类的设计原则(面向对象的基本原则)

1.开放-封闭原则
通俗:对扩展开放,对修改关闭
个软件实体如类、模块和函数应该对扩展开放,对修改关闭。模块应该尽量在不修改原代码的情况下进行扩展。
(1)通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的 public 方法。
(2)参数类型、引用对象尽量使用接口或者抽象类,而不是实现类。
(3)抽象层尽量保持稳定,一旦确定不允许修改。
2.接口隔离原则。
通俗:细节接口,客户端不应该依赖他不需要的接口,类间的依赖关系应建立在最小的接口上。
接口隔离原则的核心定义,不出现臃肿的接口,但是“小”是有限度的,首先就是不能违反单一职责原则。既要小,又得是完成一个合适大小的职责。就好像打扫房间,分成打扫卧室,打扫洗手间,打扫客厅这些就基本可以了。如果分成倒卧室垃圾桶、拖卧室地、收拾卧室的床铺…等,接口是很小,但是这样接口会太多,没必要这样设计,所以都刚刚好才好。
3.单一职责原则。
通俗:一个类只做一件事
如果一个类承担的职责过多,就等于把这些职责耦合起来,一个职责变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭到很多意想不到的破坏。而如果类的职责就一个,当我们需要这个类实现的功能有所改变的时候,只需要修改这个类就可以了。
4.迪米特法则(也称为最小知识原则)
通俗:高内聚,低耦合
一个软件实体应当尽可能的少与其他实体发生相互作用。每一个软件单位对其他软件单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。迪米特法则不希望类之间建立直接的联系。如果有真的需要建立联系的,也希望能通过他的友元类来转达。因此,应用迪米特法则有可能造成一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互关系,这在一定程度上增加了系统的复杂度。
5.依赖倒转原则。
概念:依赖倒转原则是程序要依赖于抽象接口,不要依赖于具体实现。简单的来说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块的耦合。
有时候为了代码复用,一般会把常用的代码写成函数或类库。这样开发新项目的时候直接用就行了。比如做项目的时候大多要访问数据库,所以我们把访问数据库的代码写成了函数。每次做项目去调用这些函数。
那么问题来了,我们要做新项目的时候,发现业务逻辑高层模块都是一样的,但客户却希望使用不同的数据库或存储方式,这时就出现了麻烦。我们希望能再次利用这些高层模块,但是高层模块都是与低层的访问数据库绑定在一起,没办法复用这些高层的模块。所以不管是高层模块和底层模块都应该依赖于抽象,具体一点就是接口或者抽象类,只要接口是稳定的,那么任何一个更改都不用担心。(摘抄过来的)
其实我觉得这个意思就是我们把接口的功能隔离开了,那么我们依赖这个接口的功能为目标,去实现这个接口的功能,这样我们实现的时候也是隔离开的。因为接口隔离,实现也隔离的话,那么后期修改不用大篇幅修改,小部分修改即可。

6.合成/聚合复用原则。
通俗:避免使用继承
就是在一个新的对象里面使用一些已有的对象,使之成为新
对象的一部分,新的对象通过这些对象的委派达到复用已有功能的目的。
他的设计原则是:要尽量使用合成/聚合,尽量不要使用继承。

7.里氏代换原则。
通俗:子类不能去修改父类的功能
即任何基类可以出现的地方,子类一定可以出现。里氏代换原则是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受影响时,基类才能被真正复用,而衍生类也能够在积累的基础上增加新的行为,里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。在基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
当满足继承的时候,父类肯定存在非私有的成员,子类肯定是得到了父类的这些非私有成员(假设,父类的成员全部是私有的,那么子类没办法从父类继承任何成员,也就不存在继承的概念了)。既然子类继承了父类的这些非私有成员,那么父类对象也就可以在子类对象中调用这些非私有成员。所以,子类对象可以替换父类对象的位置。
在里氏代换原则下,当需求有变化时,只需继承,而别的东西不会改变。由于里氏代换原则才使得开放封闭称为可能。这样使得子类在父类无需修改就可以扩展。

其实觉得以上七点总的来说,就是高内聚,低耦合,将功能实现合理小块化,达到低耦合、隔离的目的,达到隔离的目的是为了以后扩展的时候甚至可以将扩展的功能包装成一个类,添加到这些类当中就好了。或者说在某个以实现类的基础上再扩展就好了。还有修改功能的时候,修改实现这些功能的类就好了。所以总的来说,就是为了以后更容易扩展,修改更简单,功能分模块更清晰。

四、对象

1.基本概念

对象是类的实例化。类只是一个设计。常说类是一个图纸,里面是各种设计,各种实现方法。而对象就是根据类(图纸)建造出来的实体(房子)。可以通过对象对一些方法进行调用,实行一些操作。类是虚无缥缈的,只有将类实例化才能彰显类的作用。(这一点不绝对,因为类也可以设计成一个接口,一个类可以不实例化,可以只是起单纯的封装作用,然后给其他类继承使用,甚至可以将多个类的接口封装到一个类中,实现对这些类的功能的集合)。

2.对象与对象之间的关系

同一个类创建的对象,它们有自己的数据,但是共享一组成员函数。
数据是每个对象自己拥有的。但是成员函数之所以可以共享,是因为成员函数里有this指针(另篇文章记录),这样对象调用成员函数的时候,就知道是哪个对象调用的,对数据操纵也知道是对哪个对象的数据进行操纵。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟小胖_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值