author:
- luixiao1223
title: 处理模板化基类内的名称
例子代码
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);
...
};
class MsgInfo { ... };
template<typename Company>
class MsgSender {
public:
...
void sendClear(const MsgInfo& info)
{
std::string msg;
create msg from info;
}
Company c;
c.sendCleartext(msg);
void sendSecret(const MsgInfo& info)
{ ... }
};
问题:
template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
void sendClearMsg(const MsgInfo& info)
{
write "before sending" info to the log;
sendClear(info); //无法通过编译
write "after sending" info to the log;
}
...
};
一个特化的版本
class CompanyZ {
public:
...
void sendEncrypted(const std::string& msg);
...
};
template<> //全特化
class MsgSender<CompanyZ> {
public:
...
void sendSecret(const MsgInfo& info)
{ ... }
};
编译器会抱怨sendClear不存在。原因是,base
class可能被特化,而特化的版本可能并不提供和一般性template相同的接口。因此编译器拒绝在继承而来的名称中找sendClear。
解决方案
1
template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
...
void sendClearMsg(const MsgInfo& info)
{
write "before sending" info to the log;
this->sendClear(info); //OK, 编程人员承诺一定有sendClear
write "after sending" info to the log;
}
...
};
2
template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
using MsgSender<Company>::sendClear; // 也是告诉编译器有sendClear
void sendClearMsg(const MsgInfo& info)
{
...;
sendClear(info);
...;
}
...
};
3 最不好的一个
template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
...
void sendClearMsg(const MsgInfo& info)
{
...;
MsgSender<Company>::sendClear(info);
...;
}
};
这种调用方法,可能屏蔽掉virtual函数的动态绑定。