| 热门文章 |
 |
|
| 编辑推荐 |
 |
|
|
|
|
|
作者:中译者:叶秉哲
来源:永远的UNIX 点击: 更新:2006-12-19
|
|
来:夥伴的衍生类别不必然还是夥伴(我把你当朋友 ,但这不代表我也一定会信任你的孩子)。如果 "Base" 类别宣告了 "f()" 为它的 夥伴,"f()" 并不会自动对由 "Base" 衍生出来的 "Derived" 类别所多出来的部份 拥有特殊的存取权力。 夥伴关系的特权无递移性:夥伴类别的夥伴不必然还是原类别的夥伴(朋友的朋友不 一定也是朋友)。譬如,如果 "Fred" 类别宣告了 "Wilma" 类别为它的夥伴,而且 "Wilma" 类别宣告了 "f()" 为它的夥伴,则 "f()" 不见得对 "Fred" 有特殊的存取 权力。 ======================================== Q27:应该替类别宣告个成员函数,还是夥伴函数? 可能的话,用成员函数;必要时,就用夥伴。 有时在语法上来看,夥伴比较好(譬如:在 "Fred" 类别中,夥伴函数可把 "Fred" 弄成是第二个参数,但在成员函数中则一定得放在第一个)。另一个好例子是:二元 中序式算数运算子(譬如:"aComplex + aComplex" 可能应该定义成夥伴而非成员函 数,因为你想让 "aFloat + aComplex" 这种写法也能成立;回想一下:成员函数无 法提升它左侧的参数,因为那样会把引发该成员函数的物件所属之类别给改变掉)。 在其他情况下,请选成员函数而不要用夥伴函数。 ==================================================== ■□ 第8节:输入/输出: 和 ==================================================== Q28:该怎样替 "class Fred" 提供输出功能? 用夥伴函数 operator<<: class Fred { public: friend ostream& operator<< (ostream& o, const Fred& fred) { return o << fred.i; } //... private: int i; //只为了说明起见而设的 }; 我们用夥伴而不用成员函数,因为 "Fred" 是第二个参数而非第一个。输入的功能亦 类似,只是要改写成: istream& operator>> (istream& i, Fred& fred); // ^^^^^------- 不是 "const Fred& fred"! ======================================== Q29:为什麽我该用 而不是以前的 ? 增加型别安全、减少错误、增进效率、有延展性、提供衍生能力。 Printf 还好,而 scanf 除了容易写错之外也还算可以,然而和 C++ 的 I/O 系统相 比,它们都有其限制。C++ 的 I/O(用 "<<" 及 ">>" ),和 C( "printf()" 和 "scanf()" )相比: * 型别安全--要做 I/O 的物件,编译器会静态地事先得知其型别,而不是动态地 由 "%" 一栏查知。 * 不易出错--冗馀的资讯会增加错误的机会。C++ 的 I/O 就不需要多馀的 "%"。 * 更快速--printf 是个小型语言的「解译器」,该语言主要是由 "%" 这种东西 构成的;在执行期它用这些栏位来选择正确的格式化方式。C++ 的 I/O 系统则是 静态的依各引数真正的型别来挑选副程式,以增进执行效率。 * 延展性--C++ I/O 机制可在不改动原有程式码的情况下,就加进使用者新设计 的型态(能想像如果大家同时把互不相容的 "%" 栏位塞入 printf 和 scanf,会 是怎样的混乱场面?!)。 * 可衍生(subclassable)--ostream 和 istream(C++ 的 FILE* 代替品)都是 真正的类别,因此可以被衍生下去。这意味著:你可以让其他自定的东西有著和 stream 雷同的外表与行为,但实际上做的却是你想做的特定事情。你自动就重用 了数以万计别人(你甚至不认识它们)写好的 I/O 程式码,而他们也不需要知道 你所做的「延伸 stream」类别。 ======================================== Q30:为什麽我处理输入时,会超过档案的结尾? 因为 eof(档案结尾)的状态,是到「将要超过档案结尾的动作」才会被设定。也就 是说,读档案的最後一个位元组并不会设定 eof 的状态。 【译注】这也是 C 常见的错误。 如果你的程式像这样: int i = 0; while (! cin.eof()) { cin >> x; ++i; // work with x } 你的 i 变数就会多了一。 你真正该做的是这样: int i; while (cin >> x) { ++i; // work with x } ======================================== Q31:为什麽我的程式执行完第一次回圈後,会对输入的要求不加理睬? 因为读取数值的程式,把非数字的字元留在输入缓冲区 (input buffer) 里头了。 【译注】这也是 C,甚至 Pascal 常见的错误。 如果你的程式如下: char nam上一页 [1] [2] [3] [4] [5]
|
|
|