参考书籍:effective c++ 条款43
面向对象编程:显示接口 + 运行时多态(哪一个virtual函数被绑定 - 发生在运行期)
泛型编程 :隐式接口 + 编译时多态 (哪一个重载函数被调用 - 发生在编译期)
template注意点1:
子类不能顺利的调用模板化基类的函数
Example:
#include<iostream>
class CompanyA {
public:
void SendClear() {};
void SendSecret() {};
};
class CompanyB {
public:
void SendClear() {};
void SendSecret() {};
};
class CompanyC {
public:
void SendSecret() {};
};
template<typename Company>
class MsgSender {
public:
void SendClearMsg() {
Company c;
c.SendClear();
}
};
template<typename Company>
class LogMsgSender :public MsgSender<Company> {
public:
void Log() {
std::cout << "Loging..." << std::endl;
}
void LogSendClearMsg() {
Log();
SendClearMsg();
};
};
int main() {
LogMsgSender<CompanyA> logMsgSender;
logMsgSender.LogSendClearMsg();
std::cin.get();
}
编译出错:
问题在于:当编译器遇到LogMsgSender类时,并不知道它继承的是什么样的class ,在LogMsgSender被具现化(instantiated)之前无法知道Company是什么--更确切的说是没办法知道Company是否有个SendClear函数!(比如CompanyC就没有)
编译器往往拒绝在 templatized base class(模板化基类,Example中的MsgSender<Company>)中寻找继承而来的方法!
解决方法:
1.在 base class 函数调用之前加上this->
template<typename Company>
class LogMsgSender :public MsgSender<Company> {
public:
void Log() {
std::cout << "Loging..." << std::endl;
}
void LogSendClearMsg() {
Log();
this->SendClearMsg();
};
};
2.使用using声明:
template<typename Company>
class LogMsgSender :public MsgSender<Company> {
public:
using MsgSender<Company>::SendClearMsg;
void Log() {
std::cout << "Loging..." << std::endl;
}
void LogSendClearMsg() {
Log();
SendClearMsg();
};
};
运行成功:
Loging...
template 注意点2:
class templates 的成员函数只有在被使用时才被具现化。
比如:一个template具现化20个类,每个类15个成员函数,只有在这300个函数的每一个都被使用,你才会获得这300个函数!