C++不变式

小编 2026-07-05 阅读:674 评论:0
一、定义 前置条件:指函数履行其契约所必须满足的条件,即此函数可以执行的必须满足的条件。 后置条件:指函数执行完毕后,返回之前哪些条件是调用者可以期望的。 DbC:Design by Contract...

一、定义

前置条件:指函数履行其契约所必须满足的条件,即此函数可以执行的必须满足的条件。

后置条件:指函数执行完毕后,返回之前哪些条件是调用者可以期望的。

DbC:Design by Contract,契约式设计。

类不变式:一个或一组条件式,对于一个处于良好定义状态的对象总是真的。

 

二、举例说明

比如说,定义了一个时间类CDayTime,如下:


 
  1. class CDayTime

  2. {

  3. public:

  4.  
  5. int AddTime(int iSeconds);

  6.  
  7. private:

  8. void *m_pUser;

  9. int m_iHour;

  10. int m_iMinute;

  11. int m_iSecond;

  12. };


此类很简单,提供一个函数可以增加秒数,然后更新类的成员变量。然后此类保持一个使用者的指针。

 

类的不变式,就是使此类状态有效的条件,我们可以定义一个成员函数来表示:


 
  1. bool CDayTime::IsValid()

  2. {

  3. if (m_iHour < 0 || m_iHour > 23) return false;

  4.  
  5. if (m_iMinute < 0 || m_iMinute > 59) return false;

  6.  
  7. if (m_iSecond < 0 || m_iSecond > 59) return false;

  8.  
  9. return true;

  10. }


AddTime的前置条件可以如下:

assert(m_pUser != NULL);

前置条件并不是对输入参数的检查,而是对内部状态的检查,对某一些必须满足的条件的检查。

 

AddTime的后置条件可以如下:

assert(iRet != 0);

iRet表示函数的返回值,返回值不为0,表示失败。

后置条件是对函数返回值,或返回参数的一个期望,并不能去判断内部状态是否达到了正确的结果,也就是说CDayTime计算的结果是否正确,不能用后置条件来判断。

 

三、基于RAII的自动化检查

RAII(Resource Acquisition Is Initialization,资源获取即初始化),对象的初始化(构造函数调用)包含对它所要管理的资源的获取操作。隐含的意思:对象的析构(析构函数的调用)会自动引发资源的释放(RRID)。

如下,定义自动化检查不变性的类:


 
  1. class CheckInvariant

  2. {

  3. public:

  4. CheckInvariant(CDayTime *pTime)

  5. : m_pTime(pTime)

  6. {

  7. assert(m_pTime->IsValid());

  8. }

  9.  
  10. ~CheckInvariant()

  11. {

  12. assert(m_pTime->IsValid());

  13. }

  14.  
  15. private:

  16. CDayTime *m_pTime;

  17. }


放在AddTime中使用时,如下:


 
  1. int CDayTime::AddTime(int iSeconds)

  2. {

  3. CCheckInvariant oCheck(this);

  4. int iRet;

  5. //计算

  6.  
  7. return iRet;

  8. }

这样就保证了在函数进入和函数返回时都检查不变性。类的不变性函数中一般不放置assert,而是在外部调用处放置。

 

四、实际使用时加上编译选项

为了在实际中方便的去掉和增加这些检查机制,应该增加编译选项,且与_DEBUG或NDEBUG不一样。


 
  1. int CDayTime::AddTime(int iSeconds)

  2. #ifdef ENABLE_DBC

  3. {

  4. assert(m_pUser != NULL);

  5. CCheckInvariant oCheck(this);

  6. int iRet = uncheck_AddTime(iSeconds);

  7. assert(iRet != 0);

  8. return iRet;

  9. }

  10.  
  11. int CDayTime::uncheck_AddTime(int iSeconds)

  12. #endif

  13. {

  14. int iRet;

  15. //计算

  16. return iRet;

  17.  
版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表