模板和泛型编程的关注重点在编译期,所有的行为都在编译期确定,因此其规则和玩法也有自己特殊的一套,和其他模块不通用。
了解隐式接口和编译期多态
了解typename的双重含义
-
声明template参数时,前缀关键字class和typename可以互换
-
使用typename关键字声明嵌套从属类型名称,但不可以出现在基类列表和初始化里列表中
-
嵌套从属名称
template<typename C>
void Print2Nd(const C& container)
{
...
typename C::const_iterator iter(container.begin()) //确认是类型不是名称
...
}
//C::const_iterato 从属嵌套类型(名称中依赖于template类型参数)
学习处理模板化基类内的名称
-
在Derived class template中调用base class template的函数时,直接调用编译不过,可以使用如下方法:
-
this->xxx (建议)
-
basename::xxx
-
using basename::xxx
-
class CompanyA{
public:
CompanyA(){}
void Send()
{
cout<<"CompanyA::Send()"<<endl;
}
};
class CompanyB{
public:
CompanyB(){}
void Send()
{
cout<<"CompanyB::Send()"<<endl;
}
};
template<typename Company>
class Sender{
public:
Sender(){}
void SendMsg()
{
Company c;
c.Send();
}
};
template<typename Company>
class LogSender: public Sender<Company>
{
public:
using Sender<Company>::SendMsg;
void LogSendMsg()
{
cout<<"LogSender::LogSendMsg() before"<<endl;
SendMsg(); //单独使用错误,配合using使用ok
this->SendMsg(); //OK
Sender<Company>::SendMsg(); //OK
cout<<"LogSender::LogSendMsg() after"<<endl;
}
};
将与参数无关的代码抽取template
-
不要将函数参数提取为template,这样导致代码冗余
运用成员函数模板接受所有兼容类型
-
使用模板成员函数生成可接受和兼容所有类型的函数,包括构造函数
template<typename U>
class A
{
public:
template<typename T>
A(A<T>& other)
{
...
}
};
-
如果将构造函数声明为模板函数,为了阻止编译器生成默认的构造函数,你必须明确声明一个非模板的构造函数
需要类型转换时请为模板定义非成员函数
-
template在推倒虑隐式转换
-
对比“定义no-member函数进行类型转换”这一条规则
template<typename T>
const Rational<T> doMutliply(const Rational<T>& lhs, const Rational<T>& rhs)
{
...
}
template<typename T>
class Rational
{
public:
...
//声明为friend函数的目的是tempalte推倒,保证编译通过,根本目的是提供一个使用是所有类型的乘法
frined const Rational<T>operator*(const Rational<T>& lhs, const Rational<T>& rhs)
{
return doMutliply(lhs, rhs);
}
}
请使用traits classes表现类型信息
-
需要了解STL编程,可以参考《STL源码剖析》一书
-
运用到模板、元编程等知识
了解template元编程
-
元编程将运行期的工程提前到编译期,错误的发现更早,效率更高
分类: C++
标签: 泛型编程 模板