假设我们需要发送信息到若干个不同的公司,每个公司发送的信息分为加密和不加密的两种类型。可以利用模板技术写发送信息的类
按照书上的例子,比如现有A、B两个公司,都支持发送普通消息和加密消息。MsgSender是一个模板类,在编译器根据要给哪个公司发送消息调用相应公司的函数。这个做法是可行的。
class CompanyA
{
public:
void SendCleartext(const std::string& msg);
void SendEncrypted(const std::string& msg);
};
class CompanyB
{
public:
void SendCleartext(const std::string& msg);
void SendEncrypted(const std::string& msg);
};
template<typename Company>
class MsgSender
{
public:
void sendClear()
{
std::string msg;
Company c;
c.Sendcleartext(msg);
}
void sendSreect();
};
如果我们想多加一个功能,就是每次都记录一下发送了什么信息,我们可以用下面这个类
template<typename Company>
class LoggingMsgSender :public MsgSender <Company>
{
public:
void SendClearMsg()
{
sendClear();
}
};
但是sendClear();的调用可能会通不过编译(ps:我用的vs2008和vs2013都通过了编译。。。。这个和编译器有关),因为LoggingMsgSender继承的MsgSender<Company>中的Company是个Template参数,不到具现化时是不知道是什么的,而编译器考虑到可能会存在特化板的MsgSender template,不存在sendClear函数,所以就不能通过编译。比如只向公司Z发送加密的消息,不发送普通消息,为Z公司准备了一个特化的MsgSender template,不存在发送普通消息的函数。
class Companyz
{
public:
void sendEncrypted(const std::string& msg);
};
template <>//表明是全特化的
class MsgSender < Companyz >
{
public:
void sendClear();
};
如果这时候我们再用上面的可以添加日志的类,如果Company==Companyz,代码就不合法了,因为此时的基类MsgSender不存在sendClear函数。
所以C++,通常拒绝在模板化基类中寻找继承而来的名称(本例的sendClear)。通俗点说,就是在派生类中调用从模板化基类中继承而来的函数,因为这个函数可能不存在(特化的版本可能不存在这个函数)。
解决方式,向编译器承诺模板基类的任何特化版本都将支持其一般(泛化)版本所提供的接口。如果出现不支持一般版本所提供的接口的特化版本,还是会出现无法编译的情况。
1.在基类函数调用动作之前加上this->
this->sendClear();
2.使用using声明式
在调用之前 using MsgSender<Company>::senderClear;//也就是告诉编译器,请他假设sendClear位于基类中
3.明白指出被调函数位于基类中
MsgSender<Company>::sendClear();
请记住:
可在derived class template内通过“this->”指涉base class template内的成员名称,或借由一个明白写出的“base class资格修饰符”完成