引子:要将信息以明文或密文发送至不同的公司,当我们在编译期间(就是写代码的时候)有足够的信息决定传送至那一家公司,可以采用template的方法:
<pre name="code" class="cpp">#include <string>
using namespace std;
class CompanyA
{
public:
void SendClearTxt(const string &msg);
void SendEncrypted(const string &msg);
};
class CompanyB
{
public:
void SendClearTxt(const string &msg);
void SendEncrypted(const string &msg);
};
template<typename Company>
class MsgSender
{
public:
void sendClear(const string &msg)
{
Company p;
p.SendClearTxt("123");
}
void sendSecret(const string &msg)
{
Company p;
p.SendEncrypted("123");
}
};
上述代码可行,但是我想每次送出信息时做一些标记工作,那么自然想到derived class可以满足之,于是代码如下:
<pre name="code" class="cpp">template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
void SendClearMsg(const string &msg)
{
//...一些记日志的工作代码
sendClear("");//以明文发送出去
}
};
那么问题来了,如果有一个CompanyZ公司只接受加密的文本呢?
<pre name="code" class="cpp">class CompanyZ
{
public:
//只提供了个加密的发送方法
void SendEncrypted(const string &msg);
};
那么,上面的class LoggingMsgSender::SendClearMsg中的sendClear方法就会编译失败,如果采用下面的实现的话:
<pre name="code" class="cpp">LoggingMsgSender<CompanyZ> zMsgSender;
zMsgSender.SendClearMsg("");
分析很简单因为
CompanyZ不支持SendEncrypted的方法,从而导致基类的函数sendClear会无法编译通过。Effective C++给出三个方法来解决:
1.见下面代码
<pre name="code" class="cpp"> template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
void SendClearMsg(const string &msg)
{
//...一些记日志的工作代码
this->sendClear("");//以明文发送出去
}
};
2.使用using告诉编译器假设sendClear位于base class内
<pre name="code" class="cpp"> template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
using Msgsender<Company>::sendClear;
void SendClearMsg(const string &msg)
{
//...一些记日志的工作代码
this->sendClear("");//以明文发送出去
}
};
</pre><span style="white-space:pre"></span>3.明确指出位于base class内<span style="white-space:pre"><br /></span><pre name="code" class="cpp"> <pre name="code" class="cpp">template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
using Msgsender<Company>::sendClear;
void SendClearMsg(const string &msg)
{
//...一些记日志的工作代码
MsgSender<Company>::sendClear("");//以明文发送出去
} };
总结:其实模板化的基类的名称,当使用模板参数定义的对象时,要注意其有可能,导致driver class的实现不正确(找不到基类的方法),这时可以采取以上三种方法来明确指出。