您的位置:首页 > 编程语言 > C语言/C++

C++实现类似反射模式

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

由于我的算法对话框都是基于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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: