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元编程

{

//  算是一个模版元编程的入门介绍吧,想要了解最好看书!!!

}

时间: 2024-08-27 17:49:01

effective c++ 笔记 (45-48)的相关文章

[Effective JavaScript 笔记]第48条:避免在枚举期间修改对象

注册列表示例 一个社交网络有一组成员,每个成员有一个存储其朋友信息的注册列表. function Member(name){ this.name=name; this.friends=[]; } var a=new Member('钟二'), b=new Member('张三'), c=new Member('赵四'), d=new Member('王五'), e=new Member('阮六'), f=new Member('耿七'); a.friends.push(b); b.friends

SQL Server 2012笔记分享-48:备份时间线

备份时间线是SQL server 2012数据库恢复顾问页面中的一项重要新功能,可以让我们更方便的基于备份时间点进行数据库的恢复. 在SQL server 2012的还原数据库界面,可以找到时间线,如图. 点开时间线时候,我们可以选择还原上次所做的备份,当备份时间线的间隔选择周的时候,我们在下方的时间轴上就可以看到一周之内所有可供还原的备份. 备注:因为下图中选择了还原到上次所做的备份,所以只显示了最近一次的完整备份,如图介于7月2和7月3之间. 我们还可以选择特定的日期和时间,在时间线间隔里面

Effective C++笔记:构造/析构/赋值运算

条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函数时,编译器会给我们构造默认的. 当成员变量里有const对象或引用类型时,编译器会不能合成默认的拷贝赋值函数:当一个基类把它的拷贝赋值函数定义为private时,它的派生类也不无生成默认的拷贝赋值函数,因为它无法完成基类成份的赋值. 条款06:若不想使用编译器自动生成的函数,就该明确拒绝 将拷贝构

Effective C++笔记06:继承与面向对象设计

关于OOP 博客地址:http://blog.csdn.net/cv_ronny 转载请注明出处! 1,继承可以是单一继承或多重继承,每一个继承连接可以是public.protected或private,也可以是virtual或non-virtual. 2,成员函数的各个选项:virtual或non-virtual或pure-virtual. 3,成员函数和其他语言特性的交互影响:缺省参数值与virtual函数有什么交互影响?继承如何影响C++的名称查找规则?设计选项有如些?如果class的行为

Effective c++(笔记)之继承关系与面向对象设计

1.公有继承(public inheritance) 意味着"是一种"(isa)的关系 解析:一定要深刻理解这句话的含义,不要认为这大家都知道,本来我也这样认为,当我看完这章后,就不这样认为了. 公有继承可以这样理解,如果令class D以public 的形式继承了class B ,那么可以这样认为,每一个类型为D的对象同时也可以认为是类型为B的对象,但反过来是不成立的,对象D是更特殊化更具体的的概念,而B是更一般化的概念,每一件事情只要能够施行于基类对象身上,就一定可以应用于派生类对

Effective C++ Item 45 运用成员函数模板接收所有兼容类型

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:请使用 member function templates(成员函数模板)生成"可接受所有兼容类型"的函数 示例:泛化 copy 构造函数 temmplate<typename T> class SmartPtr{ public: template<typename U> SmartPtr(const SmartPtr<U> &o

Effective c++(笔记) 之 类与函数的设计声明中常遇到的问题

1.当我们开始去敲代码的时候,想过这个问题么?怎么去设计一个类? 或者对于程序员来说,写代码真的就如同搬砖一样,每天都干的事情,但是我们是否曾想过,在c++的代码中怎么样去设计一个类?我觉得这个问题可比我们"搬砖"重要的多,大家说不是么? 这个答案在本博客中会细细道来,当我们设计一个类时,其实会出现很多问题,例如:我们是否应该在类中编写copy constructor 和assignment运算符(这个上篇博客中已说明),另外,我们是让编写的函数成为类的成员函数还是友元还是非成员函数,

Effective C++笔记05:实现

条款26:尽可能延后变量定义式的出现时间 博客地址:http://blog.csdn.net/cv_ronny 转载请注明出处! 有些对象,你可能过早的定义它,而在代码执行的过程中发生了导常,造成了开始定义的对象并没有被使用,而付出了构造成本来析构成本. 所以我们应该在定义对象时,尽可能的延后,甚至直到非得使用该变量前一刻为止,应该尝试延后这份定义直到能够给它初值实参为止. 这样做的好处是:不仅可以避免构造(析构)非必要对象,还可以避免无意义的default构造行为. 遇到循环怎么办?此时往往我

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

js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+1}" 反射获取函数源代码的功能很强大,使用函数对象的toString方法有严重的局限性.toString方法的局限性ECMAScript标准对函数对象的toString方法的返回结果(即该字符串)并没有任何要求.这意味着不同的js引擎将产生不同的字符串,甚至产生的字符串与该函数并不相关. 如果函数

Effective c++(笔记)----类与函数之实现

上篇博客中集中说明了在设计一个类的时候常遇到的问题,当然博客中还夹杂着我随时想到的一些知识,发现自己写博客没很多人写的好,可能是自己语言不会组织,要么就是写的东西大家不愿意看,反正是有这方面的专业问题或者博客中有什么明显的错误和问题,大家提出来,我也好改进哈! 回归正题,这篇博客就大概的把Effective c++中类与函数这节看到的知识点做个笔记. 设计好一个类后,自己就要去实现这个类(实现类中的成员函数.友元.非成员函数等) 可能大家会遇到以下问题 1.在类的成员函数中,尽量避免返回内部数据