1编译器如何处理模板
编译器遇到模板的实例化时,如Grid<Spread> b,则为Spread编写另一个Grid类。会使用Spread代替模板定义中的所有的T,来编写Grid模板的Spread版的代码,有点类似宏。
在为多种数据类型实例化模板时,由于编译器会给每种数据类型都生成一个模板代码的副本,所以为多种不同的数据类型实例化模板可能会导致代码膨胀。
2模板代码在文件之间的分布
2.1在头文件中定义模板
2.2在源文件中定义模板
/*---------------------------------------------------------*/
// Grid.h
template<typename T>
clase Grid
{
}
#include "Grid.cpp"
/*-----------------------------------------------------------------*/
3.模板参数
与在构造函数中指定无类型参数相比,在模板列表指定无类型参数(诸如int和指针这类的常规参数)的主要优点是,代码在编译之前就已经知道了参数的值了。编译器是通过在编译前替换参数来为模板化方法生成代码的。因此在实现中可以使用常规的二维数组,而不用动态分配数组。
/*----------------------------------------------*/
template <typename T,int WIDTH, int HEIGHT>
// 要设定默认参数的方法为 template <typename T,int WIDTH=0, int HEIGHT=0>
class Grid
{
public:
...
protected:
T mCell[WIDTH][HEIGHT]
};
/*-----------------------------------*/
Grid<int ,10,10> myGrid;
4.方法模板
不能模板化虚方法和析构函数。
注意的一点:成员模板不会取代同名的非模板成员,由于编译器生成的代码可能有不同版本,这个规则导致了复制构造函数和operator=会存在问题。如果编写了复制构造函数和operator=的模板化版本,并去掉了非模板化的构造函数和operator=,编译器不会为同一类型的赋值运算调用这些新的模板化构造函数和operator=。相反,编译器会生成一个复制构造函数和operator=,来完成两个同类型的创建和赋值,而这并不是你想要的。因此,还必须要保留老的非模板化复制构造函数和operator=。
(这个在工程中是经常遇到的,具体见下面的示例代码)
5 模板的特殊化
可以为特定类型提供其他的类模板实现。例如,你可能针对char * 的Grid行为是无意义的。网格当前存储的是指针类型的浅副本。对于char * ,字符串的深复制可能才有意义,那么模板的特殊化就是为某个特定类型编写模板
Gird<int >myGrid1 ;//use original Grid template
Gird<char *> myGird ;//use the char * specialization
(这个在工作中还没有遇到)
6.从模板类派生子类
实例代码:
模板代码:
template <typename T>
class sp
{
public:
inline sp() : m_ptr(0) {printf("this is defult construct!\n"); }
sp(T* other);
sp(const sp<T>& other);
template<typename U> sp(U* other);
template<typename U> sp(const sp<U>& other);
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (U* other);
// Accessors
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
// Operators
private:
template<typename Y> friend class sp;
T* m_ptr;
};
// ---------------------------------------------------------------------------
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
printf("this is construct !\n");
}
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
printf("this is copy!\n");
}
template<typename T>
sp<T>::~sp()
{
printf("this desdory!\n");
}
template<typename T>
sp<T>& sp<T>::operator = (const sp<T>& other) {
printf("this is operator =\n");
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (const sp<U>& other)
{
printf("this is different sp<U> type opterator=!\n");
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (U* other)
{
printf(" this is different U type opterator=!\n");
}
//-----------------------------------------------------------------------
测试代码:
#include <iostream>
#include "sp.h"
using namespace std;
class audio
{
public:
void my_print(){ cout<<" hello!\n"<<endl;};
protected:
int a;
};
int main(void)
{
sp<audio> myaudio;
sp<audio> myaudio2;
sp<int> myvideo;
myaudio=myaudio2;
audio *ttyy=new audio();
ttyy->my_print();
sp<audio> myaudio3(ttyy);
sp<audio> myaudio4;
myaudio4=myvideo;
int *x;
sp<audio> myaudio5;
myaudio5=x;
sp<audio> tty=myaudio;
/*sp<int> my;
sp<int> you;ls
my=you;*/
return (0);
}
//-------------------------------------------------------
输出信息:
# ./test
this is defult construct!
this is defult construct!
this is defult construct!
this is operator =
hello!
this is construct !
this is defult construct!
this is different sp<U> type opterator=!
this is defult construct!
this is different U type opterator=!
this is copy!
this desdory!
this desdory!
this desdory!
this desdory!
this desdory!
this desdory!
this desdory!