1. 将需要隐式类型转换的函数声明为成员函数会出现问题 使类支持隐式转换是一个坏的想法.当然也有例外的情况,最常见的一个例子就是数值类型.举个例子,如果你设计一个表示有理数的类,允许从整型到有理数的隐式转换应该是合理的.在C++内建类型中,从int转换到double也是再合理不过的了(比从double转换到int更加合理).看下面的例子: class Rational { public: Rational(, // ctor is deliberately not explicit; ); //…
1. 非成员非友元好还是成员函数好? 想象一个表示web浏览器的类.这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: class WebBrowser { public: ... void clearCache(); void clearHistory(); void removeCookies(); ... }; 许多用户想将这些动作一块执行,所以web浏览器为此可以提供一个函数: class WebBrowser { public: ... void…
1. 问题的引入——将operator*模板化 Item 24中解释了为什么对于所有参数的隐式类型转换,只有非成员函数是合格的,并且使用了一个为Rational 类创建的operator*函数作为实例.在继续之前建议你先回顾一下这个例子,因为这个条款的讨论是对它的扩展,我们会对Item 24的实例做一些看上去无伤大雅的修改:对Rational和opeartor*同时进行模板化: template<typename T> class Rational { public: Rational(, /…
最近北京房价蹭蹭猛涨,买了房子的人心花怒放,没买的人心惊肉跳,咬牙切齿,楼主作为北漂无房一族,着实又亚历山大了一把,这些天晚上睡觉总是很难入睡,即使入睡,也是浮梦连篇,即使亚历山大,对C++的热情和追求还是不减,应该是感动了周公吧,梦境从此处开始,大师入场来给我安慰了... 11点躺在床上了,脑子里总结一下最近的工作:最近的开发用到inline函数比较多,众所周知,inline的使用是为了提高程序性能,可结果却总不尽如人意,这个捉急啊,嗯?怎么突然到了山脚下,周边树木林立,郁郁葱葱,鸟儿委婉啼叫…
看上去最为简单的(public)继承的概念由两个单独部分组成:函数接口的继承和函数模板继承.这两种继承之间的区别同本书介绍部分讨论的函数声明和函数定义之间的区别完全对应. 1. 类函数的三种实现 作为一个类设计者,有时候你只想派生类继承成员函数的接口(声明).有时候你想让派生类同时继承接口和实现,但是你允许它们覆盖掉继承而来的函数实现.但有时候你却想让派生类继承一个函数的接口和实现并且不允许它们被覆盖掉. 为了对这些不同的选择有一个更好的理解,考虑表示几何图形的类继承体系: class Shap…
1. 继承体系中关于对象释放遇到的问题描述 1.1 手动释放 关于时间记录有很多种方法,因此为不同的计时方法创建一个TimeKeeper基类和一些派生类就再合理不过了: class TimeKeeper { public: TimeKeeper(); ~TimeKeeper(); ... }; class AtomicClock: public TimeKeeper { ... }; class WaterClock: public TimeKeeper { ... }; class Wrist…
1 编译器会默认生成哪些函数  什么时候空类不再是一个空类?答案是用c++处理的空类.如果你自己不声明,编译器会为你声明它们自己版本的拷贝构造函数,拷贝赋值运算符和析构函数,如果你一个构造函数都没有声明,编译器同样会为你声明一个默认拷贝构造函数.这些所有的函数会是public和inline的(Item30).因此,如果你写了下面的类: 1 class Empty{}; 本质上来说和下面的类是一样的: 1 class Empty { 2 3 public: 4 5 Empty() { ... }…
关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样.如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为这是c++同它们不一样的地方. 假设你已经有一个为股票交易建模的类继承体系,它可以买卖股票等.这些交易的可审计性很重要,所以每次交易对象被创建的时候,需要在审计日志中创建一个合适的记录.这看上去是解决问题的合理方法: class Transaction { // base class for all…
1. 突破思维——不要将思维限定在面向对象方法上 你正在制作一个视频游戏,你正在为游戏中的人物设计一个类继承体系.你的游戏处在农耕时代,人类很容易受伤或者说健康度降低.因此你决定为其提供一个成员函数,healthValue,返回一个整型值来表明一个人物的健康度.因为不同的人物会用不同的方式来计算健康度,将healthValue声明为虚函数看上去是一个比较明显的设计方式: class GameCharacter { public: virtual int healthValue() const;…
从一开始就让我们简化这次的讨论.你有两类你能够继承的函数:虚函数和非虚函数.然而,重新定义一个非虚函数总是错误的(Item 36),所以我们可以安全的把这个条款的讨论限定在继承带默认参数值的虚函数上. 1. 虚函数是动态绑定的,而默认参数是动态绑定的 在这种情况下,这个条款的验证就相当直接了:虚函数是动态绑定的,而默认参数值是静态绑定的. 这是什么?你说你不堪重负的脑袋已经忘记了动态绑定和静态绑定之间的区别?(为了好记,静态绑定也叫做早绑定(early binding),动态绑定也叫做晚绑定(l…