• Effective C++ Item 43 学习处理模板化基类内的名称


    本文为senlie原创。转载请保留此地址:http://blog.csdn.net/zhengsenlie


    经验:可在derived class templates 内通过 "this->" 指涉 base class templates 内的成员名称,或藉由一个明确写出的 "base class 资格修饰符"完毕。


    演示样例:

    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 CompanyZ{ //这个 class 不提供 sendCleartext 函数
    public:
    	//...
    	void sendEncrypted(const std::string &msg);
    	//...
    };
    
    
    class MsgInfo {...}; 
    template<typename Company>
    class MsgSender{
    public:
    	//...
    	void sendClear(const MsgInfo &info){
    		std::string msg;
    		Company c;
    		c.sendCleartext(msg);
    	}
    	void sendSecret(const MsgInfo &info){
    		//...
    	}
    };
    
    
    template<> //一个全特化的 MsgSender;它和一般 template 同样。区别仅仅在于它删掉了 sendClear
    class MsgSender<CompanyZ>{
    public:
    	//...
    	void sendSecret(const MsgInfo &info){...}
    };
    
    
    template<typename Company>
    class LoggingMsgSender: public MsgSender<Company>{
    	//...
    	void sendClearMsg(const MsgInfo &info){
    		将”传送前“的信息写到 log
    		sendClear(info); //调用 base class 函数,这段码无法通过编译。由于全特化的版本号里没有 sendClear 这个函数
    		将”传阅后”的信息写到 log
    	}
    	//...
    };


    解析:C++知道 base class templates 有可能被特化。而那个特化版本号可能不提供和一般性 template 同样的接口,
    因此它往往拒绝在 templatized base classes内寻找继承而来的名称


    纠正1:在 base class 函数调用动作之前加上 this->
    template<typename Company>
    class LoggingMsgSender: public MsgSender<Company>{
    	//...
    	void sendClearMsg(const MsgInfo &info){
    		将”传送前“的信息写到 log
    		this->sendClear(info); //
    		将”传阅后”的信息写到 log
    	}
    	//...
    };

    纠正2:使用 using 声明式
    template<typename Company>
    class LoggingMsgSender: public MsgSender<Company>{
    	//...
    	using MsgSender<Company>::sendClear;
    	void sendClearMsg(const MsgInfo &info){
    		将”传送前“的信息写到 log
    		sendClear(info); //
    		将”传阅后”的信息写到 log
    	}
    	//...
    };

    纠正3:指出被调用的函数位于 base class 内
    template<typename Company>
    class LoggingMsgSender: public MsgSender<Company>{
    	//...
    	void sendClearMsg(const MsgInfo &info){
    		将”传送前“的信息写到 log
    		MsgSender<Company>::sendClear(info); //不太好。关闭了 "virtual 绑定行为"
    		将”传阅后”的信息写到 log
    	}
    	//...
    };

    解析:上面的每一解法做的事情都同样:对编译器承诺"base class template"的不论什么特化版本号都将支持其一般版本号所提供的接口。


    但假设这个承诺未能被实践出来,编译器还是会报错的。


    演示样例:

    LoggingMsgSender<CompanyZ> zMsgSender;
    MsgInfo msgData;
    zMsgSender.sendClearMsg(msgData); //error


  • 相关阅读:
    [BZOJ3757] 苹果树
    [WC2013]糖果公园
    [SCOI2005]王室联邦
    luogu P2709 小B的询问
    [国家集训队]小Z的袜子
    [SDOI2009]HH的项链(莫队)
    [国家集训队]数颜色 / 维护队列(莫队)
    setting>SSH>sessions setting>勾选ssh Keepalive[ MobaXterm】设置保持SSH连接
    解决SSH自动断线,无响应的问题。
    Linux下使用bcwipe擦除磁盘空间
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6727537.html
Copyright © 2020-2023  润新知