举个例子: class Student { private: int ID; string name; public: string& GetName() { return name; } }; 这是一个学生的类,类里面有两个成员变量,一个是学生ID,用整数表示,另一个是姓名,用string表示.有一个公有的方法GetName(),获得学生的名字,根据条款20所说的,使用引用可以防止资源不必要地拷贝,那么在返回值这边就用string&.但现在问题来了,这个函数只是想返回学生的姓名,并不想用…
还是举书上的例子: void PrettyMenu::changeBackground(std::istream& imgSrc) { lock(&mutex); delete bgImage; ++ imageChanges; bgImage = new Image(imgSrc); unlock(&mutex); } 这段代码大致的意思就是改变背景图片,删掉旧的背景图片,记录修改次数,然后创建新的背景图片.考虑到多线程操作,所以这里用了lock和unlock. 但这里会出现问题…
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> struct Factorial { enum { value = N * Factorial<N - >::value }; }; // 特化版本 template <> > { enum { value = }; }; int main() { cout << Fac…
这个条款从字面意思还是很好理解的,就是在使用这个变量前才去定义,而不是很早就定义了它,而在很后面的时候才去使用.这个条款只适用于对变量声明位置没有要求的语言,比如C++.对于像C或者一些脚本语言,语法要求变量声明放在函数开始处,这个条款就不能使用了. 但其实从使用的角度而言,如果不是语法的硬性要求,还是在变量使用前再去定义变量的做法比较好.这有几点原因,最直观的就是可读性比较好,程序员在阅读代码时,看到一个陌生的变量名,不用向上翻好几页才看到它的定义类型,而且对于开发者而言,也不会出现前面定义了…
在之前的理论上调用对象的operator=是这样做的 void swap(A& x) { std::swap(a, x.a); } A& operator=(const A& a) { A temp = a; swap(temp); return *this; } 上面的代码看起来有点麻烦,但它是一个好办法. 我们可以在std里面特化我们的swap class A { private: int a; public: void swap(A& x)//防止写成friend,我…
class A { private: int a; public: A(int x) :a(x){} A operator*(const A& x) { return A(a*x.a); } }; int main() { A a(); A b = a*a;//没有问题 A b = a * ;//由于构造函数没有explicit,这里隐式转换了,也没有问题 A b = * a;//出问题了 } 老师讲过,一种是类的member函数,一种是non-member函数, 但我们为了封装性,尽量不适用f…
1.格式统一 在调用的时候,不会去想有没有(),一律是有get(),或者set()之类的. 2.封装 能直接访问得越少,表明封装性越高, 封装性越高,我们的顾虑就少了, 例如:我们a.data*0.9的时候,不需要调用出来*0.9.只需用public的get()来调用在修改一下就好了 为什么不使用protected 在没有继承下的class下protected和private是一样的 但在发生了继承的情况下,原来只能用父类函数调用的数据,因为protected,完全暴露了出来. 而且,用了pri…
如果说public是一种is-a的关系的话,那么复合就是has-a的关系.直观来说,复合就是在一个类中采用其他类的对象作为自身的成员变量,可以举个例子,像下面这样: class Person { private: string Name; // 复合string类型的变量 PhoneNumber HomeNumber; // 复合PhoneNumber对象 PhoneNumber TelephoneNumber; }; 我们一般会说人有名字,有家庭电话,有手机电话等,但我们一般不会说人是一个名字…
学过基本程序课的同学都知道,inline是内联的关键字,它可以建议编译器将函数的每一个调用都用函数本体替换.这是一种以空间换时间的做法.把每一次调用都用本体替换,无疑会使代码膨胀,但可以节省函数调用的成本,因为函数调用需要将之前的参数以堆栈的形式保存起来,调用结束后又要从堆栈中恢复那些参数. 但注意inline只是对编译器的一个建议,编译器并不表示一定会采纳,比如当一个函数内部包含对自身的递归调用时,inline就会被编译器所忽略.对于虚函数的inline,编译器也会将之忽略掉,因为内联(代码展…
这一条款是说的是公有继承的逻辑,如果使用继承,而且继承是公有继承的话,一定要确保子类是一种父类(is-a关系).这种逻辑可能与生活中的常理不相符,比如企鹅是生蛋的,所有企鹅是鸟类的一种,直观来看,我们可以用公有继承描述: class Bird { public: virtual void fly(){cout << "it can fly." << endl;} }; class Penguin: public Bird { // fly()被继承过来了,可以覆…