摘要:决不要重新定义继承而来的缺省参数值#include <iostream>using namespace std;enum color{ RED,GREEN,BLACK,WHITE};class Base{public: virtual void ShowColor(color myColor = BLACK) { cout<<"Base Color is "<<myColor<<endl; }};class Derived:public Base{public: virtual void ShowColor(color myC 阅读全文
Effective C++ 学习笔记(22)
2011-08-07 13:17 by Daniel Zheng, 218 阅读, 0 推荐, 收藏, 编辑
摘要:决不要重新定义继承而来的非虚函数 假设类 D 公有继承于类B,并且类B 中定义了一个公有成员函数mf。mf的参数和返回类型不重要,所以假设都为void。换句话说,我这么写: class B {public: void mf(); ...};class D: public B { ... }; 甚至对B,D 或mf 一无所知,也可以定义一个类型D 的对象x, D x; // x 是类型D 的一个对象 那么,如果发现这么做:B *pB = &x; // 得到x 的指针pB->mf(); // 通过指针调用mf 和下面这么做的执行行为不一样:D *pD = &x; // 得到x 阅读全文
Effective C++ 学习笔记(21)
2011-08-07 00:01 by Daniel Zheng, 256 阅读, 1 推荐, 收藏, 编辑
摘要:使公有继承体现“是一个”的含义 C++面向对象编程中一条重要的规则是:公有继承意味着 "是一个"。 当写下类 D("Derived" )从类B("Base")公有继承时,你实际上是在告诉编译器(以及读这段代码的人):类型D 的每一个对象也是类型B 的一个对象,但反之不成立;你是在说:B 表示一个比D 更广泛的概念,D 表示一个比B 更特定概念;你是在声明:任何可以使用类型B 的对象的地方,类型D 的对象也可以使用,因为每个类型D 的对象是一个类型B 的对象。相反,如果需要一个类型D 的对象,类型B 的对象就不行:每个D "是 阅读全文
Effective C++ 学习笔记(20)
2011-08-06 18:34 by Daniel Zheng, 176 阅读, 0 推荐, 收藏, 编辑
摘要:千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用 先看第一种情况:返回一个局部对象的引用。它的问题在于,局部对象 ----- 顾名思义 ---- 仅仅是局部的。也就是说,局部对象是在被定义时创建,在离开生命空间时被销毁的。所谓生命空间,是指它们所在的函数体。当函数返回时,程序的控制离开了这个空间,所以函数内部所有的局部对象被自动销毁。因此,如果返回局部对象的引用,那个局部对象其实已经在函数调用者使用它之前被销毁了。 当想提高程序的效率而使函数的结果通过引用而不是值返回时,这个问题就会出现。 class Rational { // 一个有理数类public: Ration 阅读全文
Effective C++ 学习笔记(19)
2011-08-06 18:21 by Daniel Zheng, 226 阅读, 0 推荐, 收藏, 编辑
摘要:避免这样的成员函数:其返回值是指向成员的非const 指针或引用,但成员的访问级别比这个函数要低 使一个成员为 private 或protected 的原因是想限制对它的访问,对吗?劳累的编译器要费九牛二虎之力来确保你设置的访问限制不被破坏,对不对?所以,写个函数来让用户随意地访问受限的成员没多大意义,对不对?如果你确实认为有意义,那么请反复阅读本段,直到你不这样认为为止。 实际编程中很容易违反这条规则,下面是个例子: class Address { ... }; // 某人居住在此class Person {public: Address& personAddress() { ret 阅读全文
Effective C++ 学习笔记(18)
2011-08-06 09:45 by Daniel Zheng, 222 阅读, 0 推荐, 收藏, 编辑
摘要:如果不想使用隐式生成的函数就要显式地禁止它假设想写一个类模板 Array,它所生成的类除了可以进行上下限检查外,其它行为和C++标准数组一样。设计中面临的一个问题是怎么禁止掉Array 对象之间的赋值操作,因为对标准C++数组来说赋值是不合法的: double values1[10];double values2[10];values1 = values2; // 错误! 对很多函数来说,这不是个问题。如果你不想使用某个函数,只用简单地不把它放进类中。然而,赋值运算符属于那种与众不同的成员函数,当你没有去写这个函数时,C++会帮你写一个。那么,该怎么办呢? 方法是声明这个函数(operator 阅读全文
c++继承中的内存布局 <转>
2011-08-06 00:52 by Daniel Zheng, 499 阅读, 0 推荐, 收藏, 编辑
摘要:今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的。看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用。——谈VC++对象模型(美)简.格雷程化 译译者前言一个C++程序员,想要进一步提升技术水平的话,应该多了解一些语言的语意细 节。对于使用VC++的程序员来说,还应该了解一些VC++对于C++的诠释。 Inside the C++ Object Model虽然是一本好书,然而,书的篇幅多一些,又和具体的VC++关系小一些。因此,从篇幅和内容来看,译者认为本文是深入理解C++对象模型比较好 的一个出发点。这篇文章以前看到时就觉得很好,旧文重读,感觉理解得更多一些了,于 阅读全文
Effective C++ 学习笔记(17)
2011-08-06 00:09 by Daniel Zheng, 193 阅读, 0 推荐, 收藏, 编辑
摘要:在函数重载和设定参数缺省值间慎重考虑会对函数重载和设定参数缺省值产生混淆的原因在于,它们都允许一个函数以多种方式被调用:void f(); // f 被重载void f(int x);f(); // 调用 f()f(10); // 调用f(int)void g(int x = 0); // g 有一个// 缺省参数值g(); // 调用 g(0)g(10); // 调用 g(10) 那么,什么时候该用哪种方法呢? 答案取决于另外两个问题。第一,确实有那么一个值可以作为缺省吗?第二,要用到多少种算法?一般来说,如果可以选择一个合适的缺省值并且只是用到一种算法,就使用缺省参数。否则,就使用函数重载 阅读全文
Effective C++ 学习笔记(16)
2011-08-04 21:46 by Daniel Zheng, 257 阅读, 0 推荐, 收藏, 编辑
摘要:必须返回一个对象时不要试图返回一个引用看一个表示有理数的类,其中包含一个友元函数,用于两个有理数相乘:class Rational {public: Rational(int numerator = 0, int denominator = 1); ...private: int n, d; // 分子和分母friend const Rational // 参见条款21:为什么 operator*(const Rational& lhs, // 返回值是const const Rational& rhs)};inline const Rational operator*(con 阅读全文
Effective C++ 学习笔记(15)
2011-08-04 12:03 by Daniel Zheng, 217 阅读, 0 推荐, 收藏, 编辑
摘要:尽量使用“传引用”而不是“传值” C 语言中,什么都是通过传值来实现的,C++继承了这一传统并将它作为默认方式。除非明确指定,函数的形参总是通过“实参的拷贝”来初始化的,函数的调用者得到的也是函数返回值的拷贝。 “通过值来传递一个对象”的具体含义是由这个对象的类的拷贝构造函数定义的。这使得传值成为一种非常昂贵的操作。例如,看下面这个(只是假想的)类的结构: class Person{public: Person(); ~Person(); ...private: string name, address;};class Student:public Person{public: Student 阅读全文