条款41:了解隐式接口和编译期多态
- 隐式接口:模板中用到的T的接口,也就是对模板进行约束,要求T必须提供了这些接口(包含T支持的一些隐式转换),编译器才支持其成员模板的变量类型
- 编译期多态:编译器对模板的支持
条款42:了解typename的双重意义
- 代码编译阶段,如果遭遇一个嵌套从属名称(T::X),则会假设这个名称不是个类型,除非使用typename T::X来告诉编译器T::X是一个类型
- 但也有例外,描述子类继承自那个父类的时候不用;类构造函数的列表初始化时也不用;
template<typename T>
class Derived : public Base<T>::Nested //此处不用typename
{
public:
explicit Derived(int x) : Base<T>::Nested(x) //此处不用typename
{
typename Base<T>::Nested tmp;
}
};
条款43:学习处理模板化基类内的名称
- 在子模板类中,可以通过this->或父类::修饰类来显式指明父类中的一个成员名称
class MsgInfo;
template<typename Company>
class MsgSender
{
pbulic:
void sendClear(const MsgInfo& info)
{
}
};
template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
void sendClearMsg(const MsgInfo& info)
{
sendClear(info);//编译器无法编译通过,因为编译器不确定是否有
//偏特化的MsgSender<Company>,其中不包含sendClear
//以下是可以的三种方法:
//1.显式告诉编译器会从MsgSender<Company>继承sendClear
this->sendClear(info);
//2.声明
using MsgSender<Company>::sendClear;
//3.明确指出sendClear的来源
MsgSender<Company>::sendClear(info);
}
};
条款44:将与参数无关的代码抽离templates
- 需要考虑模板具象化时导致的代码膨胀问题
条款45:运用成员函数模板接受所有兼容类型
template<typename T>
class SmartPtr
{
public:
//这样只要U::heldPtr与T::heldPtr是兼容的(满足转换关系),
//SmartPtr<U>在适当的位置就可以自动转换为SmartPtr<T>
SmartPtr(const SmartPtr<U>& other) : heldPtr(other.get()){}
T* get() const { return heldPtr;}
private:
T* heldPtr;
};
条款46:需要类型转换时请为模板定义非成员函数
- 在template实参推导过程中从不将隐式类型转换函数(通过构造函数发生的隐式转换)纳入考虑
- 当编写一个类模板时,某些函数与typename相关,当这些函数的参数涉及隐式类型转换时,最好将该函数定义为类模板内的friend函数
条款47:请使用traits classed表现类型信息
(学习C++标准库后应该会有更清晰的认识)