//---------------------------15/04/06----------------------------

//#18 让接口容易被正确使用,不易被误用

{

//  1:为了防止客户输入错误的参数,可以使用外覆类型来区别:

struct Day

{

explicit Day(int d): val(d) {}

int val;

};

struct Month

{

explicit Month(int m): val(m) {}

int val;

};

struct Year

{

explicit Year(int y): val(y) {}

int val;

};

class Date

{

public:

Date(const Month& m,const Day& d,
const Year& y);

...

};

//  这时,客户职能这么使用Date class:

Date d(Month(), Day(), Year());

//  为了限制类型的值,比如一年只有12个月,Month应该反映这样的事实。

//  为了安全不直接使用enum,而是预先定义所有有效的Months:

class Month

{

public:

);}

);}

...

);}

private:

explicit Month(int m);

};

Date d(Month::Mar(), Day(), Year());

/*  2:预防客户错误的另一个办法是:限制类型内什么事可做,什么事不能做。也就是加上const。

3:除非有好理由,否则应该尽量令你的types的行为与内置types一致

4:任何接口如果要求客户必须记得做某些事情,就是有着“不正确使用”的倾向。

较佳接口的设计原则是先发制人,比如条款13中,

令factory函数返回一个智能指针,可以避免客户忘记使用智能指针:                     */

std::tr1::shared_ptr<Investment> createInvestment();

//  5:tr1::shared_ptr支持定制型删除器,可以防范DLL问题:

std::tr1::shared_ptr<Investment> createInvestment()

{

std::tr1::shared_ptr<Investment> retval(),

getRidOfInvestment);

retval = ...;

return retval;

}

}

//#19   设计class犹如设计type

{

/*  1:新type的对象应该如何被创建和销毁?

这会影响到你的class的构造函数和析构函数,以及内存分配函数和释放函数。

当然前提是如果你打算撰写他们。

2:对象初始化和对象的赋值该有什么样的差别

这个答案决定了构造函数和赋值操作符的行为,以及差异。

3:新type的对象如果被passed by value,意味着什么?

copy构造函数用来定义一个type的pass by value该如何实现。

4:什么是新type的“合法值”

你的class必须维护自己的约束条件,也就决定了你的成员函数

(特别是构造函数、赋值操作符、和所谓的setter函数)必须进行错误检查工作。

5:你的新type需要配合某个继承图系吗?

继承既有的class会受到哪些class的设计的束缚,特别是他们的函数是virtual或non_virtual的影响

如果允许别人继承自己的类,就会影响你所声明的函数是否为virtual

6:你的新type需要什么样的转换

是否需要隐式转换、显式转换。

7:什么样的操作符和函数对此新type而言是合理的?

这个答案决定你为你的class声明哪些函数,其中某些该是member函数。

8:什么样的标准函数应该驳回

你不想要系统为你声明的函数要声明为private。

9:谁该取用新type的成员

这个答案决定了哪个成员为public,protected,private。以及哪个class或function应该是friend

10:什么是新type的“为声明接口”

它对效率、异常安全性以及资源运用提供何种保证

11:你的新type有多么一般化

看看自己是否应该定义一个新的class template

12:你真的需要一个新type吗

如果只是为既有的class添加机能,那么可能单纯定义一个或多个non member函数或templates

更能达到目标。

*/

}

//#20   宁以pass by reference to const替换pass by value

{

/*  1:pass by value 需要调用copy构造函数产出一个副本,这可能使得pass by value

成为昂贵的操作。如果传递的是一个自定义class,通常需要调用一次copy构造函数加
一次析构函数

如果这个class继承自别的类,又需要多调用好几次这两个函数。

2:by reference方式传递参数可以避免slicing(对象切割)问题:

一个derived class
对象以by value方式传递并被视为一个base class对象时,base class

的copy构造函数被调用,而“造成此对象的行为属于derived class对象”的部分被切掉了,只留

下了一个base class对象。这绝不是你想要的。

3:reference通常以指针来实现出来,所以pass by reference就相当于传递指针。因此如果是一些

内置类型对象(比如int) pass by value往往比 pass by reference的效率高些。

4:除了内置类型
和 stl的迭代器和函数对象,其他的对象都以pass by reference to const

替换 pass by value。

*/

}

//#21   必须返回对象时,别妄想返回其reference

{

//  1:一些值必须返回pass by value:

//      1>通过在stack上创建对象并返回这个对象的引用:

const Rantional&
operator* (const Rantional& lhs,const Rantional& rhs)

{

Rantional result(lhs.n * rhs.n, lhs.d * rhs.d);

return result;

}

/*      这里有两个点:

1)这样也调用构造了,效率并没提高。

2)返回了一个已经被销毁的对象。严重的错误!

2>通过在堆上创建对象并返回这个对象的引用:

*/

const Rantional&
operator*(const Rantional& lhs,const Rantional& rhs)

{

Rantional result =new Rantional(lhs.n * rhs.n, lhs.d * rhs.d);

return result;

}

//      这样的话,谁负责delete?而且还是需要一次构造函数。

//      3>使用static对象:

const Rantional&
operator* (const Rantional& lhs,const Rantional& rhs)

{

static Rantional result;

result = ...;

return result;

}

//      这样首先线程不安全,其次使用if((a * b) == (c * d))总是返回true;

//  2:当一个函数必须返回新对象时,就让那个函数返回一个新对象呗!

inline
const Rantionaloperator* (const Rantional& lhs,const Rantional& rhs)

{

return Rantional(lhs.n * rhs.n, lhs.d * rhs.d);

}

}

//#22   将成员变量声明为private

{

/*  1:首先看看成员变量不该是public:

1>一致性:如果没有public成员变量,客户唯一能访问对象的办法就是使用成员函数

客户就不需要在访问成员时疑惑地试着记住是否使用小括号。

2>可以更加精准地控制成员变量:你可以通过函数控制成员变量的读写。

3>封装性:如果通过函数访问成员变量,日后就算更改了这个变量的计算方法,或者直接更改了变量,

客户也不知道,也不必知道。

不封装就意味着不改变。

2:成员变量不该是protected:

道理和public第三点一样,这样对derived class并没有封装性可言

}

effective c++ 笔记 (18-22)的更多相关文章

  1. [Effective JavaScript 笔记]第22条:使用arguments创建可变参数的函数

    第21条讲述使用可变参数的函数average.该函数可处理任意数量的参数并返回这些参数的平均值. 如何创建可变参数的函数 1.实现固定元数的函数 书上的版本 function averageOfArr ...

  2. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  3. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  4. SQL反模式学习笔记18 减少SQL查询数据,避免使用一条SQL语句解决复杂问题

    目标:减少SQL查询数据,避免使用一条SQL语句解决复杂问题 反模式:视图使用一步操作,单个SQL语句解决复杂问题 使用一个查询来获得所有结果的最常见后果就是产生了一个笛卡尔积.导致查询性能降低. 如 ...

  5. JAVA自学笔记18

    JAVA自学笔记18 1.Map接口: 1)功能: 2) Map<String,String>m=new HashMap<String,String>(); //添加元素,元素 ...

  6. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  7. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  8. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  9. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  10. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

随机推荐

  1. iis 发布asp.net mvc 网站时候js css 压缩问题,图片不加载问题

    一.JS CSS 自动压缩问题 默认情况下mvc这个框架会把css,js文件压缩成一个js或者css文件,一会发现只有一个<link href="/Content/css?v=ji3n ...

  2. sqlserver tablediff 实用工具

    tablediff 是sqlserver自带的实用工具 sqlserver 2012 在110目录下,sqlserver2008在100目录下 官方参考文档如下: https://docs.micro ...

  3. 小米正式开源 SQL 智能优化与改写工具 SOAR

    近日,小米正式宣布开源 SOAR. 截至今日,该项目已经获得了 350 个「star」以及 44 个「fork」(GitHub项目地址:https://github.com/XiaoMi/soar) ...

  4. od 转储 二进制文件常用命令

    od :  NAME od - dump files in octal and other formats 常用命令: ➜ Downloads od -t x1 -Ax /etc/ld.so.cach ...

  5. oracle like模糊查询简单用法

    like  用法介绍: 1.“_”:匹配单个任意字符 select * from bqh3 where name like '_崔'; 2.“%”:匹配0个或多个任意字符.但有三种情况如下: like ...

  6. 2018亚太CDN峰会开幕, 阿里云王海华解读云+端+AI的短视频最佳实践

    4月11-12日,2018亚太CDN峰会在北京隆重召开,在11日下午的短视频论坛中,阿里云高级技术专家王海华进行了<短视频最佳实践:云+端+AI>的主题演讲,分享了短视频的生命周期关键点和 ...

  7. 卸载CocoaPods

    1. 移除pod组件 这条指令会告诉你Cocoapods组件装在哪里 : $ which pod 你可以手动移除这个组件 : $ sudo rm -rf <path> 2.移除 RubyG ...

  8. Alpha冲刺报告(1/12)(麻瓜制造者)

    任务分配 这是我们在leangoo上的任务分配: 具体分工如下: 登录界面的编码:邓弘立 肖小强 浏览.检索商品:杜宏庆 汪志彬 待出售的商品: 李佳铭 江郑 数据库建表: 符天愉 刘双玉 图书捐赠模 ...

  9. RLP(转发注明出处)

    目录 RLP序列化 什么是序列化? 为什么要序列化? RLP序列化处理的两项数据 RLP序列化采取的5项规则: 利用python写的RLP 实际中的使用是个怎么样子? RLP分析 参考目录 @ RLP ...

  10. 【2018暑假集训模拟一】Day1题解

    T1准确率 [题目描述] 你是一个骁勇善战.日刷百题的OIer. 今天你已经在你OJ 上提交了y 次,其中x次是正确的,这时,你的准确率是x/y.然而,你最喜欢一个在[0; 1] 中的有理数p/q(是 ...