C++编码规范八 (模板编程)
预编译头文件
浅层实例化:底层模板往往是在实例化上层模板的过程中被实例化的。因此,一旦因为底层模板的错误而导致上层模板不能被正确的实例化,编译器所给出的诊断信息通常会包含对产生这个问题的所有层次的完整跟踪。程序员往往很难从这么多信息中快速找到症结所在.
在程序中增加一些不可能执行的哑代码,只是为了在实例化上层模板时,提前验证一下所用模板实参能否满足底层模板所需要的操作,这种编程技巧称为浅层实例化。
template<typename T>
void shell(void){
class Shallow{
void deref(T::P const& p){ //提前执行
*p = 0;
}
};
typename T::P p;
middle<T> (p);
}
class Object{
public:
//typedef int* p;
typedef int p;
};
追踪器:
是一个用户自定义的类,可以作为测试模板功能和性能的类型实参,对于被跟踪模板的每一个操作,跟踪器都应该由一个对应的跟踪动作。
class Tracer{
public:
Tracer(void);
Tracer(int data);
Tracer(Tracer const& that);
Tracer& operator=(Tracer const& rhs);
~Tracer(void);
private:
int m_data;
};
//.cpp
Tracer::Tracer(void){
cout << "缺省构造:"<<this<<endl;}
Tracer::Tracer(int data):m_data(data){
cout << "有参构造:"<<this<<endl;}
Tracer::Tracer(Tracer const& that):m_data(that.m_data){
cout << "拷贝构造:"<<&that<<"->"<<this<<endl;}
Tracer& Tracer::operator=(Tracer const& rhs){
cout << "拷贝赋值:"<<&rhs<<"->"<<this<<endl;
m_data = rhs.m_data;
return *this;}
Tracer::~Tracer(void){
cout <<"析构函数:"<<this<<endl;}
如何识别地址内存位置:
栈地址:十六进制,8位,一般bf开头,地址比较高
堆地址:十六进制,7位,一般8开头,地址比较低
静态多态:模板多态
成员函数选择是在编译阶段执行的。不需要虚函数指针,甚至可以做内联优化
代价是牺牲了内存空间,性能提升。但是灵活性差一点,只能代表一种类型
静态多态 将同一个操作作用于不同的对象,却可以产生不同的结果,谓之多态。基于虚函数的多态通常被称为动态多态,而基于模板的多态则为静态多态。相较于动态多态,静态多态具有更好的时间性能,而且代码更加简洁。
动态多态:虚函数性能不好一个原因是在运行阶段找函数指针去调用函数,第二个是不能做内联优化。编译阶段用函数代码代替函数调用。
通过模板函数推断 同样实现多态 。
#include<iostream>
using namespace std;
class Rect{
public:
void draw(void) const
{
cout << "绘制矩形"<<endl;
}
};
class Circle{
public:
void draw(void) const
{
cout << "绘制圆形"<<endl;
}
};
//多态函数
template<typename Shape>
void drawAny(Shape const& shape){
shape.draw();
}
int main(void){
drawAny (Rect());
drawAny(Circle());
return 0;
}