一 模板与宏
- 宏在预处理阶段处理,模板在编译阶段处理
- 宏不会检查类型,只是文本替换,而模板会进行类型检查
- 模板只有实例化后才会产生代码
二 函数模板
- 将相同功能的函数模板化
2.1 定义
template <class或者typename T>
返回类型 函数名(形参表)
{
函数定义体
}
// 定义一个函数模板
template<typename T>
T sum(T a, T b)
{return a + b;
}
2.1 不同类型的模板参数
- 我们不但可以使用不同类型的模板参数,还可以将模板参数作为函数的返回值
template<typename T1,typename T2,typename T3>
void sum(T1 a, T2 b,T3 &c)
{c = a + b;
}
2.3 成员函数模板
class Product
{
public:template<typename T>void setProduct(const T& t){qDebug()<<t;}
};Product product;product.setProduct<const char*>("生产者");
三 模板函数
- 强调的是函数:是由一个函数模板生成而来的函数
3.1 生成模板函数
- 我直接使用qt的数据类型也是可以成功运行处预期的结果的
// 模板函数// intint iSum = sum<int>(1,999);// floatfloat fSum = sum<float>(1.0021f,999.123f);// QStringQString sSum = sum<QString>("你好","世界");qDebug()<<iSum<<fSum;
四 命名隔离
- 如果在外部定义了一个与模板类型相同的命名,模板并不会受到影响,也就是说模板内部是相对隔离的。
typedef QString T;
template<typename T>
T sum(T a, T b)
{return a + b;
}
- 当然你不能把这个重命名放在模板里面
template<typename T>
T sum(T a, T b)
{typedef QString T;return a + b;
}
五 问题
5.1 同一类型的模板参数不能多次定义
template<class T,class T>
5.2 有一个以上的模板参数时,每个都必须指定类型
template<class T,T2> // 这是错误的
// 必须这样写
temlpate<class T,class T2>
5.3 inline/constexpr不能写在模板声明处
inline template<classT> // 错误格式
// 正确格式应该是卸载函数前
template<class T>
inline void sum(T a, T b);
5.4 extern声明如果调用了就必须实现
- 如果定义了一个这种extern声明了一个函数,并且程序中会调用这个模板来生成模板函数,那么这个模板就必须完成定义
- 相反如果没有调用,其实是可以不用定义的
- 同样的inline和constexpr也一样
template<typename T>
extern void sum(T a);