开发者社区> 异步社区> 正文

《C++面向对象高效编程(第2版)》——2.21 确保抽象的可靠性——类不变式和断言

简介:
+关注继续查看

本节书摘来自异步社区出版社《C++面向对象高效编程(第2版)》一书中的第2章,第2.21节,作者: 【美】Kayshav Dattatri,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.21 确保抽象的可靠性——类不变式和断言

C++面向对象高效编程(第2版)
任何抽象都必须与客户履行它的契约(contract)。当客户使用类时,他希望类的对象像其发布描述的那样运行正常。另一方面,类的实现者必须千方百计地确保对象运行正常。但是,类只有在客户履行自己那部分契约后,才能正确行使它的职责。例如,类的成员函数可能要求传入的参数为非零指针(non-zero pointer)。只有满足此前提条件,成员函数才能保证它的行为。因此,客户必须履行一些义务。换言之,如果客户履行了她那部分契约,对象的实现者必须尊重客户那部分契约,并确保正当的行为。

在类和成员函数的文档中说明契约,这个主意不错。但是,把这些契约条件作为类的一部分实现代码,在执行类实现时检测契约条件,效果更好。这体现了断言(assertion)的巨大价值所在。

通常,断言是一个用于评估真假的表达式。如果表达式评估为假,则断言失败。例如,在TlaserDiscPlayer类中,Play成员函数会包含一个托盘关闭的断言。稍后即将介绍它的语法。

2.21.1 类不变式

进一步研究发现,在每个成员函数中(或甚至在一个成员函数的内部的多处)都包含一个断言可能并不方便。每个类都会在对象中包含一些恒为真的条件,无论对象调用任何成员函数,这些条件都必须为真。这样的条件称为类不变式(class invariant)。顾名思义,在对象中这些条件恒为真。如果我们以某种方式给类添加这些条件,并保证每个成员函数的代码都检查这些条件,将会非常方便。

2.21.2 前置条件和后置条件

除这些类不变式之外,成员函数可能会包含其他条件,在执行代码前必须保证这些条件为真。这些在操作开始被调用之前必须为真的条件,称为前置条件(precondition)。

C++:

在C和C++中,断言已经使用很长一段时间。所有的C和C++编译器都支持assert宏。该宏接受一个表达式,而且必须判断表达式的真假。倘若表达式判断为真,则继续执行;倘若表达式为假,则程序停止,并显示错误消息表明断言失败。消息中包含文件名,违规的语句源代码行号。这是最简单的(且唯一可用的)断言形式。Play成员函数的断言代码如下:

TLaserDiscPlayer::Play(unsigned atChapter)
{
  // 这是断言代码
  assert(this->_trayStatus == eClosed);
  // 略去其余代码
}```
Play成员函数在被调用之前,要求影碟播放机托盘关闭,这个条件表示为断言。
一旦成员函数完成它的操作,将会执行某些条件必须为真的断言。换言之,如果成员函数成功地执行完毕,它将生成一个满足某些条件的结果,这样的条件被称为后置条件(postcondition)。

Eiffel:

在Eiffel中,前置条件和后置条件都是非常流行的概念,而且得到了很好的支持。Eiffel运行期系统检查这些条件,并确保它们为真,否则,停止正在运行的程序。在require子句中,前置条件置于操作的开始。操作的后置条件将在操作末尾的ensure子句中说明。按照这样的方式,每个操作不管在何处被调用,都可以自由地使用任何前提和后置条件。

在进入和退出每个操作(成员函数)时,都必须检查类不变式。为了让实现者便于使用它,我们最好能将所有的不变式都置于类内部的已知区域。类不变式就是在对象的生命期内,必须保证对象状态的语句。例如,Person抽象中可能包含某个不变式,用于保证人的出生日期必须为有效数据,且姓名正确。与此类似,不允许透支的BankAccount抽象中可能包含余额不能小于零的不变式。这些不变式功能强大,它们允许实现者清楚地规定类的某些特性。客户在使用类的对象时,可以认为这些条件为真。

C++和Smalltalk都没有内置支持类不变式,但是Eiffel内置支持类不变式。

Eiffel:

在Eiffel中,类不变式定义在类内部的invariant区,每个操作内部都会检查它们。特别是,在进入和退出每个操作时,会检查类不变式是否为真。这确保可以随时预测类对象的行为。实际上,操作的每个前置条件和后置条件都包含对类不变式的判断。

###2.21.3 使用断言实现不变式和条件
既然C++未直接支持类不变式,我们就必须设法构造一些策略来达到类似的效果。assert宏可以在这派上用场,以下就是一个简单的策略。

简单地定义一对宏:PRE_CONDITION和POST_CONDITION,它们使用assert宏。

define PRE_CONDITION(condition) assert(condition)

define POST_CONDITION(condition) assert(condition)`

如果需要,可以在这些宏中添加消息,当断言失败时打印消息。

#define PRE_CONDITION(message, condition) assert( (message, (condition)))
#define POST_CONDITION(message, condition) assert( (message, (condition)))```
当断言失败,希望打印失败消息时,这会有所帮助。例如,你可以编写以下代码:

`PRE_CONDITION(“Laser disc tray is not closed”, (_trayStatus==eClosed));`
虽然这样的前置条件和后置条件只是简单的断言,但是,它们让程序更可靠、更易读,而且更加易于理解。

然而,添加对类不变式的支持并不容易。记住,在每次进入和退出每个成员函数时,类不变式都必须为真。要保证这一点,需要在一个函数(名为InvariantChecker)中定义一组条件,且在每次进入和退出每个成员函数时,都调用该函数。这样的方法冗长且易出错,因为每个成员函数必须要调用这个函数。如果在类中添加新函数,这样的方法甚至更易出错。但是,却没有其他可行的办法,有总比没有好。如果没有其他办法,至少要在文档中清楚地说明,用户才能明确地知道实现者所保证的契约是什么。很多类的设计者提供非常清楚的类不变式文档,并遵循一些策略确保不变式被强制执行。

注意:
当使用任何一种策略时,都要根据需要添加可关闭或开启策略的支持(一对`#ifdef`)。
###2.21.4 高效使用断言
高效使用断言可实现更可靠的程序。当条件不成立时,断言至少保证程序不会继续执行。但是发生断言失败,就不可能再复原。要解决这个问题,需要用到C++支持的真正的异常管理工具(参见第10章)。但是,理解和使用异常并不容易,它需要适当的架构和高效的设计。断言简单且易于实现,众多程序员已经使用多年。

hand即使你并不打算精心设计程序,但至少要练习使用简单的断言。

不要认为一旦开始使用断言,就不能转用其他更好的处理方式。如果将来决定使用真正的异常管理,只需在代码中找到所有调用assert的地方,然后用适当的throw语句替换即可。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【Flutter】Dart 面向对象 ( 抽象类 | 抽象方法 )
【Flutter】Dart 面向对象 ( 抽象类 | 抽象方法 )
21 0
继承用法大全——c++面向对象编程(必看)
继承用法大全——c++面向对象编程(必看)
13 0
Joshua Bloch使用的“失败原子性”是什么?它对不可变对象有何好处?
Joshua Bloch使用的“失败原子性”是什么?它对不可变对象有何好处?
5 0
Java入门 - 语言基础 - 04.对象和类
Java作为一种面向对象语言。支持以下基本概念: - 多态 - 继承 - 封装 - 抽象 - 类 - 对象 - 实例 - 方法 - 重载 本节我们重点研究对象和类的概念。
225 0
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
10017 0
《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一2.2.2 VIPLE的活动和服务
本节书摘来华章计算机《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一书中的第2章 ,第2.2.2节,陈以农 陈文智 韩德强 著 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2038 0
《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一2.2.1 VIPLE的工程设计过程
本节书摘来华章计算机《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一书中的第2章 ,第2.2.1节,陈以农 陈文智 韩德强 著 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2619 0
+关注
异步社区
异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
12049
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载