zoukankan      html  css  js  c++  java
  • C++实现类似反射模式

         在编写遥感算法工具箱的时候,工具都是在xml文件中配置好的,在工具箱上构建一棵树根据xml配置文件,然后通过双击不同的树节点,弹出不同的算法对话框。最简单的方式就是使用if else 或者switch case之类的条件判断语句来实现,但是这个太不方便了,每增加一个算法,都要在分支上添加一个条件谈判,用现在流行的话说就是太不给力了。于是想通过一个比较通用的方式来解决这个问题。

    image

        由于我的算法对话框都是基于MFC的CDialog,所以可以通过算法对话框的类名来创建各自的对象,然后将对话框显示。以前知道在Java和C#中有一个反射模式,就是可以通过类名来创建一个类的对象。但是C++是没有这个东东的,于是就查找资料,终于用C++的模板实现了类似的功能。下面贴代码:

    /** /file RegistClassName.h 
    * 图像数据处理对话框反射模式
    */
    
    #ifndef REGISTCLASSNAME_H
    #define REGISTCLASSNAME_H
    
    #include 
    #include 
    #include 
    using namespace std;
    
    
    /**
    * @brief 重定义对象
    */
    typedef CDialog*(*pf)();
    
    /**
    * /class ClassMap RegistClassName.h 
    * @brief 类映射
    */
    class ClassMap
    {
    private:
        /**
        * @brief 私有构造函数
        * 为了让这个类不产生实例对象
        */
        ClassMap() { }
    
        /**
        * @brief 以类名为键的一个存放着构建方法的Hash表
        */
        static map<string, pf> m_ClassMap;
        
    public:
        /**
        * @brief 定义一个类必须注册一下
        * @param _className 类名
        * @param _createFun 注册函数指针
        */
        static void RegistClass(string _className, pf _createFun)
        {
            if(m_ClassMap.find(_className) != m_ClassMap.end())
                return; //已经注册过,直接返回
    
            m_ClassMap[_className] = _createFun;
        }
    
        /**
        * @brief 私有构造函数
        * @param _className 类名
        */
        static CDialog* forName(string _className)
        {
            if(m_ClassMap.find(_className) == m_ClassMap.end())
                return NULL;    //没有找到类对象,返回NULL
            else
                return (m_ClassMap[_className])();
        }
    };
    
    /**
    * @brief 以类名为键的一个存放着构建方法的Hash表
    */
    __declspec(selectany) map<string, pf> ClassMap::m_ClassMap;
    
    /**
    * /class DelegatingObject RegistClassName.h 
    * @brief 委派模板类
    */
    template<typename T>
    class DelegatingObject 
    {
    public:
        /**
        * @brief 构造函数
        * @param _className 类名
        */
        DelegatingObject(string _className)
        {
            ClassMap::RegistClass(_className, &(DelegatingObject::Create));
        }
    
        /**
        * @brief 创建实例函数
        */
        static CDialog* Create()
        {
            return static_cast<CDialog*>(new T);
        }
    };
    
    /**
    * @brief 注册类的宏定义
    */
    #ifndef REGIST_CLASS
    #define REGIST_CLASS(X) DelegatingObject<X> __class_##X( #X );
    #endif
    
    #endif //REGISTCLASSNAME_H

    这样只要在各自的算法对话框的Cpp文件前面添加下面一句话即可:

    REGIST_CLASS(CRasterTransformDlg); //栅格文件格式转换
    REGIST_CLASS(CVectorTransformDlg); //矢量文件格式转换
    

    然后在调用算法的地方按照下面使用方法即可,这样就不用写一大批的if或者switch语句了:

    BOOL ShowAlgoDialog(string strDlgName) 
    { 
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        CDialog * pDlg = (ClassMap::forName(strDlgName)); 
    
        if(pDlg == NULL) 
        { 
            AfxMessageBox("该类没有注册,请检查!",MB_OK);
            return FALSE; 
        }
        
        pDlg->DoModal();
        return TRUE;
    }
  • 相关阅读:
    Exsi上Windows主机增加硬盘容量
    第6章:vuerouter,vuecli和单文件组件
    Python之爬取天气预报并生成图表
    第3章:vue生命周期及实例的属性
    Python 获得NOAA全球开放气象数据
    第5章:组件即组件间的通信
    MACBOOK M1 PRO 下运行.NET CORE(MAC下如何与X86_64兼容)
    DOTNET 运行AESGCM程序 ON MACOS(错误ALGORITHM ‘AESGCM’ IS NOT SUPPORTED ON THIS PLATFORM)
    1.3\~1.4 控制措施类型、安全框架
    mac 安装brew带来的种种问题
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6314065.html
Copyright © 2011-2022 走看看