zoukankan      html  css  js  c++  java
  • 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


  • 相关阅读:
    STM32F746G-DISCO官方例程烧写
    zedboard学习第一篇
    itop4412开发板添加开机启动程序
    dsp6657的串口学习
    开源SLAM
    非线性滤波(信号处理)
    图形学领域的关键算法及源码链接
    基于倾斜影像的城市三维场景重建
    基于RFID恢复信号场
    对“自然语言处理”的理解
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6727537.html
Copyright © 2011-2022 走看看