条款 46: 宁可编译和链接时出错,也不要运行时出错

        运行时错误的概念和 C++没什么关系,就象在 C 中一样。没有下溢,上溢,除零检查;没有数组越界检查(运行时错误),等等。一旦程序通过了编译和链接,你就得靠自己了----  一切后果自负。

        现在的情况下,它的含义就是要避免运行时错误。只要有可能,就要让出错检查从运行时退回到链接时,或者,最理想的是,编译时。

        这种方法带来的好处不仅仅在于程序的大小和速度,还有可靠性。如果程序通过了编译和链接而没有产生错误信息,你就可以确信程序中没有编译器和链接器能检查得到的任何错误,仅此而已。

        对于运行时错误来说,情况大不一样。在某次运行期间程序没有产生任何运行时错误,你就能确信另一次不同的运行期内不会产生错误吗?运行时发现错误比在编译链接期间检查错误更不能让人放心。

        通常,对设计做一点小小的改动,就可以在编译期间消除可能产生的运行时错误。这常常涉及到在程序中增加新的数据类型(参见条款 M33) 。

       假设想写一个类来表示时间中的日期,最初的做法可能象这样:

       

class Date {
public:
Date(int day, int month, int year);
...
};
       准备实现这个构造函数,面临的一个问题是对 day 和 month 值的合法性检查。

      一个明显的办法是采用枚举类型而不用整数:

enum Month { Jan = 1, Feb = 2, ... , Nov = 11, Dec = 12 };
class Date {
public:
Date(int day, Month month, int year);
...
};

遗憾的是,这不会换来多少好处,因为枚举类型不需要初始化:

Month m;
Date d(22, m, 1857); // m 是不确定的
所以,Date 构造函数还是得验证 month 参数的值。

既想免除运行时检查,又要保证足够的安全性,你就得用一个类来表示month,你就得保证只有合法的 month 才被创建:

class Month {
public:
<span style="color:#ff0000;">static const Month Jan() </span>{ return 1; }
static const Month Feb() { return 2; }
...
static const Month Dec() { return 12; }
<span style="color:#ff0000;">int asInt() const </span>//  为了方便,使 Month
{ return monthNumber; } //  可以被转换为 int
private:
Month(int number): monthNumber(number) {}
const int monthNumber;
};
class Date {
public:
Date(int day, const Month& month, int year);
...
};
        这个设计在几个方面的特点综合确定了它的工作方式。首先, Month 构造函数是私有的这防止了用户去创建新的 month。可供使用 的只能是 Month 的静态成员函数返回的对象,再加上它们的拷贝。第二, 每个 Month 对象为 const,所以它们不能被改变(否则,很多地方会忍不住将一月转换成六月,特别是在北半球)。 最后一点, 得到 Month 对象的唯一办法是调用函数或拷贝现有的 Month通过隐式 Month 拷贝构造函数----  见条款 45) 。这样,就可以在任何时间任何地方使用 Month 对象;不必担心无意中使用了没有被初始化的对象。 (否则就可能有问题。条款 47 进行了说明)
        Date 的例子 将运行时检查用编译时检查来取代,你可能想知道什么 时候可以使用链接时检查。实际上,不是经常这么做。C++ 用链接器来保证所需要的函数只被定义一次(参见条款 45,"需要"  一个函数会带来什么) 。 它还使用链接器来保证静态对象(参见条款 47)只被定义一次。你可以用同样的方法使用链接器。例如,条款 27 说明, 对于一个显式声明的函数,如果想有意禁止对它进行定义,链接器检查就很有用。






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值