effective c++ 笔记 (45-48)
//#45 运用成员函数模版接受所有兼容类型
{
/* 1:当你使用智能指针的时候,会发生一个问题,想把一个子类的对象赋给基类的指针变得不可能了,
因为智能指针指定了的是基类的类型,而赋给它的是一个它的子类的对象。
2:解决办法,使用成员函数模版,可以分别对拷贝构造函数和赋值操作进行模版化: */
template<class T>
class SmartPtr
{
public:
//为了防止什么不管什么类型都来进行转换,可以使用一个get()函数来防止这样的情况。
//这样只有指针存在隐式转换才会进行转换,否则就报错了。
template<class U>
SmartPtr(const SmartPtr<U>& other): heldPtr(other.get())
T* get()
const { return heldPtr;}
template<class U>
SmartPtr<T>&
operator=(const SmartPtr<U>& other)
{
heldPtr = other.get();
return *this;
}
};
/* 3:你声明的泛化的拷贝构造函数和赋值函数
并不能阻止编译器为你生成 正常版本的
这两个函数
所以如果想要控制传入一样类型时的情况:也就是U等于T时,你必须自己实现正常版本的函数。*/
}
//#46 需要类型转换时请为模版定义非成员函数
{
// 1:考虑#24下的非成员函数的隐式类型转换,如果现在加上template,那么就行不通了,看起来像这样:
template<class T>
const Rational<T>
operator*(const Rational<T>& r1,
const Rational<T>& r2)
{ ...}
/* 如果你有一个Rational<int>类型的 Ra,并且做了这样的运算 Ra * 6,抱歉,不能通过编译
这是因为编译器只能找到左边那个参数,Ra它是知道是Rational<int>的,但是看看右边的参数
int?
不认识,没有相应函数。
2:所以为了让编译器认识它,你必须把这个函数声明成Rational类的friend函数。这样编译器在找到
第一参数的时候,就确定了这个函数处于Rational<int>的类中,然后int类型的6就自然而然地隐式
转换成Rational<int>类型了。
3:但是这样还是无法链接,因为链接器只找到了声明缺不知道定义,因为我们定义的是模版函数,除非你
再实现一个专门针对int类型的operator。但是这样模版的意义何在?
所以最简单的办法就是直接在类内部实现定义式。
4:在类内部实现定义式会造成一个问题:隐式inline,如果这个操作很复杂会造成代码膨胀,那就只能
选择调用一个外部函数,因为是inline,所以不会产生效率问题,多棒。
5:来看看具体实现吧 */
template<class T>
const Rational<T> doMultiply(const Rational<T>& r1,
const Rational<T>& r2)
{ ...}
template<class T>
Rational
{
...
friend const Rational<T>
operator*(const Rational<T>& r1,
const Rational<T>& r2)
{
return doMultiply(r1,r2)}
}
// 6:doMultiply无法隐式转换,但是它不需要这样的转换,因为friend函数已经把正确的类型传入了。
}
//#47 请使用traits classes
表现类型信息
{
/* c++并不能动态知道一个迭代器的类型,所以我们需要一个巧妙的技巧,那就是traits
比如我想要对单向,双向,随机迭代器分别调用一个函数的不同版本,可以借助iterator_traits: */
template<class Iterator>
void dosomething(Iterator iter)
{ _dosomething(iter,iterator_traits<Iterator>::iterator_category())}
// 这样就可以借助传入的参数来判断迭代器的类型了。
// 这里说的很简略,主要是这东西不是简单能叙述的,详细内容可以参考stl源码剖析。
}
//#48 认识template元编程
{
// 算是一个模版元编程的入门介绍吧,想要了解最好看书!!!
}
effective c++ 笔记 (45-48)的更多相关文章
- [Effective JavaScript 笔记]第48条:避免在枚举期间修改对象
注册列表示例 一个社交网络有一组成员,每个成员有一个存储其朋友信息的注册列表. function Member(name){ this.name=name; this.friends=[]; } va ...
- Effective Java笔记一 创建和销毁对象
Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第3章:使用函数--个人总结
前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- java effective 读书笔记
java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...
- Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer
Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...
- Item 5:那些被C++默默地声明和调用的函数 Effective C++笔记
Item 5: Know what functions C++ silently writes and calls 在C++中,编译器会自己主动生成一些你没有显式定义的函数,它们包含:构造函数.析构函 ...
随机推荐
- 错误: 未能完成程序集的安装(hr = 0x8007000b),.net程序关于使用Oracle.DataAccess.dll不同版本x86和x64问题,即oracle odp.net 32位/64位版本的问题
如果你的机器上安装了odp.net,且确信machine.config也有类似以下结节:(64位+.net 4.0环境下,machine.config可能会有4份,分别对应于.net2.0/4.0的3 ...
- innodb_locks_unsafe_for_binlog分析
mysql数据库中默认的隔离级别为repeat-read. innodb默认使用了next-gap算法,这种算法结合了index-row锁和gap锁.正因为这样的锁算法,innodb在可重复读这样的默 ...
- QT的setwindowflags的属性总结
:setWindowFlags(Qt::CustomizeWindowHint);//设置窗口标题栏自定义 setWindowFlags(Qt::WindowMinimizeButtonHint);/ ...
- [Redis_1] Redis 介绍 && 安装
0. 说明 Redis 介绍 && 安装 1. Redis 介绍 2. Redis 安装(Windows 10) [2.1 解压 redis-2.2.2-win32-win64.rar ...
- 使用AndroidStudio上传忽略文件至SVN Server的解决措施
在同组项目进行共享时,容易把本地的配置文件比如*.iml等文件上传至共享服务器,这样会对队友造成巨大的麻烦,为了解决这个问题,可以使用下面方法解决,下面以上传到服务器的app.iml文件为例. 一.在 ...
- 【转】Java学习---Java核心数据结构(List,Map,Set)使用技巧与优化
[原文]https://www.toutiao.com/i6594587397101453827/ Java核心数据结构(List,Map,Set)使用技巧与优化 JDK提供了一组主要的数据结构实现, ...
- mysql数据库中导入txt文本数据的方法
安装好MySQL和Navicat 8 for MySQL 通过Navicat 8 for MySQL创建数据库test. 2 在数据库test上创建测试数据表student(主键ID,姓名,年龄,学 ...
- SNMP协议利用
1.安装snmp服务 2.配置snmp服务 运行Services.msc 添加社区public,只读 启动服务 3.在kali运行 Snmpwalk -c public -v 2c IP 即可查看目标 ...
- 投稿核心期刊、中文重要期刊、SCI二区及以上期刊目录
大家在研究生期间想必均经历过投稿核心期刊的烦恼,不知道哪些是核心期刊,那些是普通期刊,万一选的不对岂不是浪费了时间,因此小顾在网络上收集了了2018北大核心期刊目录及全国中文重要期刊目录和SCI二区及 ...
- C++构造析构函数生命期及对象生命期