effective c++ 笔记 (45-48)
2015-04-26 09:47
197 查看
//#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元编程
{
// 算是一个模版元编程的入门介绍吧,想要了解最好看书!!!
}
{
/* 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 C++ 45-48
- Effective C++ 45-48
- 《Effective C++》:规定44-规定45
- Effective C++ 阅读笔记(二)public继承与继承中的函数覆盖
- Effective C++ (E3 5、6)笔记之禁止默认拷贝构造和赋值重载操作符
- (三)java业务场景篇笔记库(45)
- Effective C++规定45 附加代码
- jQuery学习笔记45--项目美化实例
- Effective C++ 笔记:4设计与声明
- Java学习笔记48. 小感想——工具的发明与改进
- effective C++ 3rd 笔记(一)
- Effective C++_笔记_条款05_了解C++默认编写并调用哪些函数
- 《Effective C++》笔记:I
- 为“异常安全的努力”是值得的——effective c++学习笔记
- Effective C++(条款45-47)
- EffectiveC++学习笔记-条款45
- Effective C++学习笔记:条款2:尽量用iostram而不用stdio.h
- effective c++ 笔记 (31-34)
- Effective C++ 08 别让异常逃离析构函数 笔记