条款41 了解隐式接口和编译期多态
//显式接口:函数的签名式(函数名称、参数类型、返回类型)构成
class Widget{
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap(Widget& other);
};
//隐式接口 由表达式组成
template<typename T>
void do(T & t)
{
if(w.size() > 10 && w != some)
{
...
//它必须提供一个名为size的成员函数,该函数返回一个整数值
//它必须支持一个operator!= 函数,用于比较两个T对象
编译期多态是因为template通过具现化和函数重载解析发生在编译期。
条款42 了解typename的双重意义
template<class T>class w;
template<typename T>class w;
//两者意义相同 没有什么不同
//一般性规则:任何时候当你想要在template中指涉一个嵌套从属类型名称,就必须在它前一个位置放置关键字typename
//依赖于template的参数称为从属名称 从与名称在class中呈嵌套状,称为嵌套从属名称
template <typename C>
void print(const C& container)
{
if(container.size() >= 2)
{
typename C::const_iterator iter(container.begin());//一般性依赖
...
}
声明template参数时,前缀关键字class和typename可互换
一般性原则使用时必须使用template。
条款 43 学习鼓励模板化基类内的名称
可在派生类模板内通过this->指向基类模板中的名称
条款 44 将与参数无关的代码抽离template
看不懂=-=
条款45 运用成员函数模板接受所有兼容类型
template <tpename T>
class SmartPtr{
public:
template<typename U>
SmartPtr(const SmartPtr<U> & other)
:heldPtr(other.get()){...} //以other的heldPtr初始化this的heldptr
T* get() const {return heldPtr;}
...
private:
T* heldPtr;
};
条款46 需要类型装换时请为模板定义非成员函数
template<typename T>
class Rational{
public:
Rational(const T& numberator = 0,const T& denominator = 1);
const T numerator() const;
const T denominator() const;
...
};
template<typename T>
const Rational<T> operator * (const Rational<T>& lns,const Rational<T>& rhs)
{...}
//调用
Rational <int> oneHalf(1,2);
Rational <int> result = oneHalf * 2;//错误,无法通过编译
template<typename T> class Rational;
template<typename T> const Rational <T> doMultiplt(const Rational<T> & lhs,
const Rational<T>& rhs);
template<typename T> class Rational{
public:
....
friend const Rational<T> operator*(const Rational<T>& lhs, const Rational<T>& rhs)
{
return doMultiplt(lhs,rhs);
}
};
template<typename T> const Rational <T> doMultiplt(const Rational<T> & lhs,
const Rational<T>& rhs)
{
return Rational<T>(lhs.numerator()* rhs.numerator(),lhs.denominator * rhs.denominator());
}
//作为一个template,doMultiply不支持也不需要支持混合式乘法,它只被operator *调用,而operator支持 混合式操作。
当我们编写class template,它所提供的 与此template相关的 函数支持 所有参数的隐式类型转换时,请将那些函数定义为 class template 内部的friend函数。
条款47 请使用traits classes 表现类型信息
分解迭代器相关问题-=-=
条款48 认识template元编程(TMP)
//计算阶层的元模板
template<unsigned n>
struct Factorial{ //n*n-1
enum{ value = n * Factorial<n-1>::value};
};
template<> //考虑特殊情况<0>值为1
struct Factorial<0>{
enum { value = 1};
};
int main()
{
std::count<<Factorial<5>::value;
std::count<<Factorial<10>::value;
return 0;
}
TMP可以将工作由运行期移往编译区,因而得以实现早期错误侦测和更高的执行效率。
条款49 了解 new-handler的行为
就是详细的解释了一下new 的行为
条款50 了解new和delete的合理替换时机
理由:
1用来检测运用上的错误。比如内存泄露
2为了强化效能
3为了收集使用上的统计数据
条款51 编写new和delete时需要固守常规
operator new 应该内含一个无穷循环,并在其中尝试分配内存,如果无法满足内存需求,就应该调用new-handler。它也应该有能力处理0bytes申请
条款52 写了placement new 也要写placement delete
自定义new函数要写配套,且不要无意识的遮掩了他们正常的版本
条款53 不要忽略编译器的警告
严肃对待编译器发出的警告信息,努力在最高警告级别下没有警告。
条款54 让自己熟悉包括TR1在内的所有标准程序库
TR1中添加了智能指针,一般化函数指针,以及其他组件。
条款55 让自己熟悉Boost
boost.org