- 以不同template参数具现化function templates会导致调用不同的函数,这便是所谓的编译器多态;哪一个重载函数被调用也是发生在编译期
- 如果template内出现的名称如果相依于某个template参数,称之为从属名称。如果从属名称在class内呈嵌套状,我们称它为嵌套从属名称,如果解析器在template中遭遇一个嵌套从属名称,它便假设这个名称不是个类型,除非你告诉它是。比如 C::const_iteator* x;需要在前面加上typename;但是又两个例外,typename不可以出现在八色 classes list内的嵌套从属名称之前,也不可以在member initialization list中作为base class修饰符
- 可在derived class template内通过“this->”指涉base class template内的成员名称,或者通过using
class CompantA { public: ... void sendCleartext(const std::string& msg); void sendEncrypted(const std::string& msg); ... }; ```javascript class CompantB { public: ... void sendCleartext(const std::string& msg); void sendEncrypted(const std::string& msg); ... }; ... class MsgInfo{...}; //这个class用来保存信息,以备将来产生信息 template<typename Company> class MsgSender{ public: ... void sendClear(const MsgInfo& info) { std::string msg; Company c; c.sendCleartext(msg); } void sendSecret(const MsgInfo& info) {...} };
当编译器遭遇class template LoggingMsgSender定义式时,并不知道它继承什么样的class,当然它继承的是MsgSender< Company >,但其中的Company是个参数,不到LoggingMsgSender被具现化无法确切知道它是什么。而如果不知道Company是什么,就无法知道class MsgSender< Company >是否有个sendClear函数template<typename Company> class LoggingMsgSender:public MsgSender<Company> { public: ... void sendClearMsg(const MsgInfo& info) { sendClear(info); //调用base class函数;这段代码无法通过编译 } };
class CompanyZ { public: ... void sendEncrypted(const std::string& msg); //这个函数不提供sendCleartext函数 };
这就是为什么C++拒绝这个调用的原因:它知道base class template有可能被特化,而特化版本可能不提供和一般性template相同的接口template<> class MsgSender<CompanyZ> //一个全特化版本的MsgSender,差别只是它删掉了sendClear { public: ... void sendSecret(const MsgInfo& info) {...} };
有三个办法,第一是在base class函数调用动作之前加上“this->”:
第二个是使用using声明式template<typename Company> class LoggingMsgSender:public MsgSender<Company> { public: ... void sendClearMsg(const MsgInfo& info) { this->sendClear(info); } };
第三个做法是明白指出被调用的函数位于base class内:template<typename Company> class LoggingMsgSender:public MsgSender<Company> { public: using MsgSender<Company>::sendClear; ... void sendClearMsg(const MsgInfo& info) { sendClear(info); } };
但是这往往不令人满意,如果被调用的是virtual函数,上述的明确资格修饰会关闭“virtual绑定行为”template<typename Company> class LoggingMsgSender:public MsgSender<Company> { public: ... void sendClearMsg(const MsgInfo& info) { MsgSender<Company>::sendClear(info); } };
- template实参推导过程中从不将隐式类型转换函数纳入考虑,当我们编写一个class template,而它所提供之与此template相关的函数支持所有参数之隐式类型转换时,请将那些函数定义为class template内部的friend 函数