快速业务通道

C++箴言:如何访问模板化基类中的名字

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-30
没有意义。为了纠正这个问题,我们可以创建一个 MsgSender 针对 CompanyZ 的特化版本:
template<> // a total specialization of
class MsgSender<CompanyZ> { // MsgSender; the same as the
public: // general template, except
... // sendCleartext is omitted
void sendSecret(const MsgInfo& info)
{ ... }
};

  注意这个 class definition(类定义)开始处的 "template <>" 语法。它表示这既不是一个 template(模板),也不是一个 standalone class(独立类)。正确的说法是,它是一个用于 template argument(模板参数)为 CompanyZ 时的 MsgSender template(模板)的 specialized version(特化版本)。这以 total template specialization(完全模板特化)闻名:template(模板)MsgSender 针对类型 CompanyZ 被特化,而且这个 specialization(特化)是 total(完全)的——只要 type parameter(类型参数)被定义成了 CompanyZ,就没有剩下能被改变的其它 template''s parameters(模板参数)。
  已知 MsgSender 针对 CompanyZ 被特化,再次考虑 derived class(派生类)LoggingMsgSender:
template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
 public:
 ...
 void sendClearMsg(const MsgInfo& info)
 {
  write "before sending" info to the log;
  sendClear(info); // if Company == CompanyZ,
  // this function doesn''t exist!
  write "after sending" info to the log;
 }
 ...
};

  就像注释中写的,当 base class(基类)是 MsgSender<CompanyZ> 时,这里的代码是无意义的,因为那个类没有提供 sendClear function(函数)。这就是为什么 C++ 拒绝这个调用:它认可 base class templates(基类模板)可以被特化,而这个特化不一定提供和 general template(通用模板)相同的 interface(接口)。结果,它通常会拒绝在 templatized base classes(模板化基类)中寻找 inherited names(继承来的名字)。在某种意义上,当我们从 Object-oriented C++ 跨越到 Template C++,inheritance(继承)会停止工作。
  为了重新启动它,我们必须以某种方式使 C++ 的 "don''t look in templatized base classes"(不在模板基类中寻找)行为失效。有三种方法可以做到这一点。首先,你可以在调用 base class functions(基类函数)的前面加上 "this->":
template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
...
void sendClearMsg(const MsgInfo& info)
{
 write "before sending" info to the log;
 this->sendClear(info); // okay, assumes that
 // sendClear will be inherited
 write "after sending" info to the log;
}
...
};

  第二,你可以使用一个 using declaration,如果你已经读过《C++箴言:避免覆盖通过继承得到的名字》,这应该是你很熟悉的一种解决方案。该文解释了 using declarations 如何将被隐藏的 base class names(基类名字)引入到一个 derived class(派生类)领域中。因此我们可以这样写 sendClearMsg:
template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
 using MsgSender<Company>::sendClear; // tell compilers to assume
 ... // that sendClear is in the
 // base class
 void sendClearMsg(const MsgInfo& info)
 {
  ...
  sendClear(info); // okay, assumes that
  ... // sendClear will be inherited
 }
 ...
};

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号