effective c++摘
来源:互联网 发布:233网校软件 编辑:程序博客网 时间:2024/06/16 06:16
item 46 通过friend实现参数的隐式转换
很自然的,一个有理数类的模板形式如下:
template <typename T>struct Rational{ Rational(const T& numerator=0,const T& denominator=1) { }}template <typename T>const Rational<T> operator*(const Rational<T>& lhs, const Rational<T>& rhs){}
但是它不支持
Rational<int> oneHalf(1,2);Rational<int> result = 2*oneHalf;
编译器无法从operator*调用动作中推测出使用哪个函数。因为在template实参推导过程中从不将隐式类型转换函数纳入考虑。此处不考虑“通过构造函数而发生的“隐式类型转换,解决这个问题,只要利用一个事实:
template class内的friend声明式可以指涉某个特定函数
Rational类变成了:
template <typename T>struct Rational{ Rational(const T numerator=0,const T denominator=1) { } friend const Rational& operator*(const Rational& lhs, const Rational& rhs) { }};
这项技术的一个有趣点是,我们虽然使用friend,却与friend的传统用途毫不相干。为了让类型转换可能发生于所有实参身上,我们需要一个non-member参数;为了令这个函数被自动具现化,我们需要将它声明在class内部;而在class内部声明non-member函数的唯一办法就是:令它成为一个friend。
这里必须把operator*定义也放到Rational内,因为如果只是一个声明,编译器在实例化Rational时,会寻找针对该实例的operator*的定义,然而找不到,链接就无法通过。
解决这个问题可以通过引入一个辅助函数,最后的形式如下:
//这个前置声明 work for doMultiply的声明template <typename T>struct Rational;//不能在这里进行定义,因为我们还不知道Rational的结构template <typename T>const Rational<T> doMultiply(const Rational<T>& lhs, const Rational<T>& rhs);template <typename T>struct Rational{ Rational(const T numerator=0,const T denominator=1) { } friend const Rational& operator*(const Rational& lhs, const Rational& rhs) { return doMultiply(lhs, rhs); }};template <typename T>const Rational<T> doMultiply(const Rational<T>& lhs, const Rational<T>& rhs){ //坐真正需要做的事}
item 47 traits技术
原书讲的太透彻了
item 48 template元编程
在编译期计算阶乘的例子:
template <int n>struct Factorial{ enum {value=n*Factorial<n-1>::value};};template <>struct Factorial<0>{ enum {value=1};};int main(){ printf("%d\n",Factorial<10>::value);}
但有一些局限:
只能求在编译器就能确定的整数的阶乘;
不能判别参数为负的情况;
当嵌套层数过深时编译器会报 fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
这个例子中并没有对模板进行具现,所以工作都放在了编译期。
把enum换成static成员也是一样的:
template <int n>struct Factorial{ static int value;};template <int n>int Factorial<n>::value=Factorial<n-1>::value*n;template <>struct Factorial<0>{ static int value;};int Factorial<0>::value=1;int main(){ printf("%d\n",Factorial<3>::value);}
其他
item 04
不同编译单元non-local static对象的初始化次序无法保证,可以通过转化为local static对象来解决,但要考虑多线程下的初始化不确定性。
item11
确保当对象自我赋值时有良好的行为,技术包括比较两个对象的地址,临时存储原对象指针,copy-and-swap。
派生类中的函数会掩盖基类中的同名函数,无关参数,函数名的掩盖是语法分析时发生的,function signature是编译器生效的。
private继承中的派生类不会像public继承那样可以向基类转换,因为public继承描述的是is-a关系,private继承不是。
- 《Effective C++》和《More Effective C++》汇总
- 《Effective C++》读书笔记
- 《Effective C#》 翻译札记
- 《Effective C++》读感
- 《Effective C++》读后感
- 读《Effective C++》所想
- 《Effective C++》读书笔记
- 《Effective C#》 翻译札记
- 细读《Effective C++》之一
- 《Effective C#》 翻译札记
- effective c sharp 印象
- 细读《Effective C++》之一
- Begin reading 'Effective c++'
- 《Effective C#》 翻译札记
- 《Effective c++》读书笔记
- 《Effective C++》 笔记
- Effective C++(1-4)
- Effective C++(5-12)
- Java序列化对象的存储和读取
- 交易相关模块
- 多线程系列 - 上下文切换
- 【安卓】android studio 项目gradle 中的各种版本统一
- leetcode_[python/C++]_395_Longest Substring with At Least K Repeating Characters_(递归非递归)
- effective c++摘
- Java对象初始化详解(转)
- Django信号1内置
- 【NOIP2013 day2】华容道 题解
- Word基础笔记
- 【JZOJ4890】【NOIP2016提高A组集训第14场11.12】随机游走
- LeetCode 459. Repeated Substring Pattern
- 关于Java面试中sql优化的问题浅析
- android与js相互调用(2)基本用法