//---------------------------15/04/08----------------------------

//#23   宁以non_member、non_friend替换member函数

{

class WebBrowser

{

public:

...

void clearCache();

void clearHistory();

void removeCookies();

...

};

/*  对于上面这个函数,有的客户会想一次调用这三个函数,那么时使用member函数好呢,

还是non_menber non_friend函数好呢

1:对于封装性来说,是non_member版本比较好。

1>从封装开始讨论:如果某东西被封装,它就不再可见。愈多东西被封装,愈少人可以看到它。

而愈少人看到它,就有愈大的弹性去变化它,因为我们的改变仅仅直接影响看到改变的那些人事物。

就这一点来说,能够访问private成员变量的就是成员函数和friend函数。如果non_member和

member函数提供的功能是相同的,那么,封装性较大的是non_member函数,因为它不增加”能访问

class内private成分“的数量。

2>member函数说的只是针对能访问到private成员的类,并不是说这个函数不能是别的类的member函数。

2:把这些non_member函数放入namespace并分类到不同的头文件中。这么做的原因是,客户可以针对不同的

功能,包含不同的头文件。

*/

}

//#24   若所有参数皆需类型转换,请为此采用non_member函数

{

//  令class支持隐式类型转换通常是个糟糕的主意。然而也有例外,最常见的例外是在建立数值类型时。

//  如果要设计一个有理数的类,让他支持int隐式转换到有理数还是很合理的

class Rational

{

public:

Rational(,
)//没有使用explicit,允许隐式转化

int numerator()
const;

int denominator()
const;

private:

};

//  让有理数类支持+ *等操作时,使用non_member函数实现,类内部的operatpr*()操作无法实现全部功能。

const Rational
operator*(const Rational& rhs)const;

Rational oneHalf(,),result;

;  //可以正确调用operator*()操作,2在参数列表中,可以隐式转换

result = * oneHalf;  
//错误,没有这样的操作

//  结论:只有当参数被列于参数列表内,这个参数才是隐式类型转换的合格参与者。

//  所以,只能使用non_member函数,把两个数都放入参数列表中

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

{

return Rational(lhs.numerator() * rhs.numerator(),

lhs.denominator() * rhs.denominator());

}

//  是否让它成为friend的?没有必要,不是friend就能完成任务,就不必成为friend了

}

//#25   考虑写出一个不抛异常的swap函数

{

//  swap原本是stl的函数:

namespace std

{

template<typename T>

void swap(T& a, T& b)

{

T temp(a);

a = b;

b = temp;

}

}

//  这种调用方式,在某些情况,会产生不必要的消耗:

class WidgetImpl

{

public:

...

private:

int a,b,c;

stad::vector<double> v;//意味着复制需要的时间很长

};

class Widget

{

public:

Widget(const Widget& rhs);

Widget&operator=(const Widget& rhs)

{

...

*pImpl = *(rhs.pImpl); //深拷贝

...

}

private:

WidgetImpl* pImpl;

};

//  当执行swap的时候,正常情况应该直接交换两个 pImpl的指针,而stl版本的却要复制三个widgetImpl对象

//  为了特化,可以声明一个成员函数对指针调用swap函数:

class Widget

{

public:

void swap(Widget& other)

{

using std::swap;

swap(pImpl, other.pImpl);

}

...

};

namespace std

{

template<>

void swap<Widget>(Widget& a, Widget& b)

{

a.swap(b);

}

}

//  当Widget时个class template时,这么做是错的:

namespace std

{

template<typename T>

void swap< Widget<T> >(Widget<T>& a, Widget<T>& b)

{

a.swap(b);

}

}

//  这样是在偏特化 swap的函数模版参数,并不是偏特化swap函数,所以可以使用重载:

namespace std

{

template<typename T>

void swap(Widget<T>& a, Widget<T>& b)

{

a.swap(b);

}

}

//  然而我们不能往std中添加新的东西。所以我们可以把non_member函数放到Widget的namespace那儿

namespace WidgetStuff

{

template<typename T>

class Widget{...};

...

template<typename T>

void swap(Widget<T>& a, Widget<T>& b)

{

a.swap(b);

}

}

//  使用

template<typename T>

void doSomething(T& obj1, T& obj2)

{

using std::swap;       
//为了std的swap可见,至于调不调用是编译器的事

...

swap(obj1, obj2);

}

/*  swap总结:

1>提供一个public swap成员函数,让它高效地置换你的类型的两个对象值。

2>在你的class或template所在的命名空间内提供一个non_member swap,并令它调用上述swap成员函数

3>如果你编写的class不是class template。为你的class特化std::swap,并令让调用swap成员函数。

4>在使用swap时,记得使用 using std::swap,使得std::swap可见。

5>成员版swap绝对不能抛出异常。

*/

}

effective c++ 笔记 (23-25)的更多相关文章

  1. [Effective JavaScript 笔记]第25条:使用bind方法提取具有确定接收者的方法

    js里方法和属性值为函数,就像一个东西两种称呼一个样,比如土豆,也叫马铃薯,一个样.既然一样,那就可以对对象的方法提取出来为函数,然后把提取出来的函数作为回调函数直接传递给高阶函数. 高阶函数是什么 ...

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

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

  3. Item 5:那些被C++默默地声明和调用的函数 Effective C++笔记

    Item 5: Know what functions C++ silently writes and calls 在C++中,编译器会自己主动生成一些你没有显式定义的函数,它们包含:构造函数.析构函 ...

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

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

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

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

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

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

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

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

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

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

  9. java effective 读书笔记

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

  10. Ext.Net学习笔记23:Ext.Net TabPanel用法详解

    Ext.Net学习笔记23:Ext.Net TabPanel用法详解 上面的图片中给出了TabPanel的一个效果图,我们来看一下代码: <ext:TabPanel runat="se ...

随机推荐

  1. 转:Web 开发中很实用的10个效果【附源码下载】

    原文地址:http://www.cnblogs.com/lhb25/p/10-useful-web-effect.html 在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多 ...

  2. Tmux 使用教程 on Fedora 28

    Tmux 和 gun/screen 都是优秀的终端复用软件,它的关键的好处就是,保持ssh 登录连接session不中断,并且能支持分屏操作,具备丰富的命令行参数,可以进行动态布局和操作.可以看作为s ...

  3. python基础学习15----异常处理

    异常处理,是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况(即超出程序正常执行流程的某些特殊条件). 1.异常的类型 异常的类型多种多样,常见的异常有: AttributeE ...

  4. 【转】Nginx学习---深入浅出Nginx的介绍

    [原文]https://www.toutiao.com/i6595428119933354500/ Nginx是一款轻量级的Web服务器.反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在 ...

  5. 记录一次优化mysql查询语句的方法

    今天在数据库中导入大量的数据,大概有25万条,结果在查询的时候优化没有做好,因此导致查询意外停止或者是直接查询程序中止,很是苦恼.所以才有了优化查询的方法总结 1.首先是查看一下数据量 2.接下来按照 ...

  6. October 16th 2017 Week 42nd Monday

    The more decisions that you are forced to make alone, the more you are aware of your freedom to choo ...

  7. [ML学习笔记] 回归分析(Regression Analysis)

    [ML学习笔记] 回归分析(Regression Analysis) 回归分析:在一系列已知自变量与因变量之间相关关系的基础上,建立变量之间的回归方程,把回归方程作为算法模型,实现对新自变量得出因变量 ...

  8. 1083. [SCOI2005]繁忙的都市【最小生成树】

    Description 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造.城市C的道 路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路 ...

  9. Android MaterialDesign之水波点击效果的几种实现方法

    什么是水波点击的效果? 下面是几种不同的实现方法的效果图以及实现方法   Video_2016-08-31_003846 如何实现? 方法一 使用官方提供的RippleDrawable类 优点:使用方 ...

  10. Spring Boot Actuator RCE

    来看一下IDEA如何调试Spring Boot 先在https://github.com/artsploit/actuator-testbed下载源码 如下命令就能通过maven环境启动 mvn in ...