Effective C++学习笔记_条款43:学习处理模板化基类内的名称

  有两个不同的公司,想发送不同的消息给这个两个公司,消息可以是明文,也可以是译成密码的形式发送。于是我们采用动态绑定。先定义一个发送消息的类BaseSendMsg,包含SendMsgTxt以及SendMsgSecret两个virtual函数,然后另外定义两个类CompanyA和CompanyB,这两个类分别继承BaseSendMsg,并分别重写自己的发送消息的函数。
  但是我们这里想换一种思路,使用静态的方法来实现,即采用template技术来实现:

 class CompanyA
 {
 public:
      void SendClearText(){}
      void SendEncryptedText(){}
 };

 class CompanyB
 {
  public:
     void SendClearText(){}
     void SendEncrypedText(){}
 };

 template <class T>
 class MsgSender
 {
 public:
     void SendClearText(){}
 };

 template <class Company>
 class MsgSenderWithLog: public MsgSender<Company>
 {
 public:
     void SendClearTextWithLog()
     {
         // Logs
         SendClearText(); // 有的编译器会编不过这段代码
     }
 };

 int main()
 {
     MsgSenderWithLog<CompanyA> MsgSender;
     MsgSender.SendClearTextWithLog();
 }

  上述的SendClearTextWithLog函数的定义还是挺好的,因为它避免遮掩“继承而得的名称(见条款33)”,也避免重新定义一个继承而得的non-virtual函数。但上述代码无法通过编译,,至少对严守规律的编译器而言。这样的编译器会抱怨sendClearText不存在。但是我们能看见sendClearText确实存在base class内,编译器却看不到,为什么?
  问题在于当编译器遭遇class template MsgSenderWithLog定义式时,并不知道它继承什么样的class,当然它继承的是MsgSender< Company>,但其中的Company是个template参数,不到后来(当MsgSenderWithLog被具现化)无法确切知道它是什么。
  这就是静态方法的“在模板化基类”内寻找继承而来的名称的问题所在。为了重头来过,我们必须有某种办法令C++“不进入templatized base classes观察”的行为失效,有三个办法:
  1. 在base class函数调用动作之前加上“this->”:

template <class Company>
class MsgSenderWithLog: public MsgSender<Company>
{
public:
    void SendClearTextWithLog()
    {
        // Logs
        this->SendClearText(); // 成立,假设SendClearText将被继承
    }
};

  2. 使用using声明式

template <class Company>
class MsgSenderWithLog: public MsgSender<Company>
{
public:
    using MsgSender<Company>::SendClearText;//告诉编译器,请它假设SendClearText位于base class

    void SendClearTextWithLog()
    {
        SendClearText(); // 成立,假设SendClearText将被继承      
    }
};

  3. 明白指出被调用的函数位于base class内:

template <class Company>
class MsgSenderWithLog: public MsgSender<Company>
{
public:
    void SendClearTextWithLog()
    {
        ...
        MsgSender<Company>::SendClearText(); // 成立,假设SendClearText将被继承
            ...
    }
};

  但这往往是最不让人满意的一个解法,因为如果被调用的是virtual函数,上述的明确资格修饰会关闭“virtual绑定行为”。

请记住: 可在derived class内通过“this->”指涉base class templates内的成员名称,或藉由一个明白写出的“base class资格修饰符”完成。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值