静态map成员的一种替代方法
2015-11-13 14:20
447 查看
问题场景
解决方法
尝试一
尝试二
尝试三
尝试四
其他思路
if else之类的太“俗”了,想通过一种更为优雅的方式来实现,有什么方法?
那么,问题来了:这个静态的map成员如何初始化?
假如map类型的对象_op_list是某一个类的一般成员变量(没有static修饰),那么_op_list可以在构造函数中赋值完成实例化
如果有static修饰的话,static变量初始化的语法是: <数据类型><类名>::<静态数据成员名>=<值> 即:
这时候就默认的构造了一个空的map,接下来想要像全局函数一样赋值:
这是不可以的!
所以,这样做也不可行。
boost固然强大,但是这么一个小问题就是用boost的话,未免过“重”了。
定义一个初始化类
在包含TaskInterface类中, 声明一个init类型的static变量
调用_build_map的构造函数并将_op_list传入
这个方法能够解决问题,但是却莫名其妙的多了一个init类,和我们要解决的业务逻辑毫无关系,它的存在仅仅是为了初始化类TaskInterface的static map对象。
还有没有别的解决方法呢?看起来优雅的那种。
我的方法:用一个静态结构体数组来替代静态map。这个思路来源于许多开源代码中的选项操作的实现,比如nginx、ffmpeg中都有用到类似的方法来处理选项。
代码如下:
测试代码就不贴了。
总体来说,这个方法还算优雅,如有其他思路,欢迎交流。
解决方法
尝试一
尝试二
尝试三
尝试四
其他思路
问题场景
有一个task接口类,存在一个对task操作的op_proxy静态函数,task可能有多种不同类型的操作,现在要实现这个op_proxy,原型为:int op_proxy(const std::string &task_id, const std::string &op_type);
if else之类的太“俗”了,想通过一种更为优雅的方式来实现,有什么方法?
解决方法
一般来说可以这么做,在task接口类中新增一个静态的map程序变量op_list,来保存操作类型和操作函数之间的映射,类似这样:#ifndef _TASK_INTERFACE_H_ #define _TASK_INTERFACE_H_ #include <string> #include <map> typedef int (*OpFun)(const std::string &); class TaskInterface { public: static int op_proxy(const std::string &task_id, const std::string &op_type); public: static std::map<std::string, OpFun> _op_list; }; #endif //_TASK_INTERFACE_H_
那么,问题来了:这个静态的map成员如何初始化?
尝试一
初始化map的问题在于要给map附一个初始值,可是map的默认构造中不能像数组一样直接赋值:int a[3] = {1, 2, 3};
假如map类型的对象_op_list是某一个类的一般成员变量(没有static修饰),那么_op_list可以在构造函数中赋值完成实例化
TaskInterface::TaskInterface() { _op_list["run"] = op_task_run;//op_task_run为run命令的操作函数 ...... }
如果有static修饰的话,static变量初始化的语法是: <数据类型><类名>::<静态数据成员名>=<值> 即:
std::map<std::string, OpFun> TaskInterface::_op_list;
这时候就默认的构造了一个空的map,接下来想要像全局函数一样赋值:
TaskInterface::_op_list["run"] = op_task_run;
这是不可以的!
尝试二
现在考虑把赋值定义在某个函数中,这样的话只有在函数被调用的时候,map变量才会被初始化。可是问题是我们的期望是在执行main之前并且在类的构造函数调用之前,这个map变量就已经实例化并且已经赋值,因为可能在某些其他地方也需要使用这个map变量中的值。所以,这样做也不可行。
尝试三
先定义一个全局数组,用数组来初始化这个map变量。可是如果已经有这样一个全局数组的话,那么这个map变量显得就多余了。另外怎么用它初始化这个map变量?可以使用超强的boost::map_list_of。boost固然强大,但是这么一个小问题就是用boost的话,未免过“重”了。
尝试四
网上找的一种解决思路,用一个初始化类来初始化这个静态map成员:定义一个初始化类
class init { inline void init(map<int, int>& a) { // 初始化 a }; };
在包含TaskInterface类中, 声明一个init类型的static变量
class TaskInterface { public: static std::map<std::string, OpFun> _op_list; static init _build_map;//为了初始化_op_list };
调用_build_map的构造函数并将_op_list传入
std::map<std::string, OpFun> TaskInterface::_op_list;//先初始化为空的map init TaskInterface::_build_map(_op_list);//再初始化
这个方法能够解决问题,但是却莫名其妙的多了一个init类,和我们要解决的业务逻辑毫无关系,它的存在仅仅是为了初始化类TaskInterface的static map对象。
还有没有别的解决方法呢?看起来优雅的那种。
其他思路
既然静态map成员初始化如此费尽,为什么一定要用static map呢?!我的方法:用一个静态结构体数组来替代静态map。这个思路来源于许多开源代码中的选项操作的实现,比如nginx、ffmpeg中都有用到类似的方法来处理选项。
代码如下:
//op_task.h 文件,声明了所有task的操作函数,及静态的_op_list变量 #ifndef _OP_TASK_H_ #define _OP_TASK_H_ #include <string> typedef int (*OpFun)(const std::string &); struct OpInfo { std::string _op_type; OpFun _op_fun; }; class OpTask { public: static int op_task_run(const std::string &task_id); static int op_task_pause(const std::string &task_id); static int op_task_retry(const std::string &task_id); static int op_task_stop(const std::string &task_id); public: static OpInfo _op_info_list[]; }; #endif //_OP_TASK_H_
//op_task.cpp 文件,操作函数的实现及_op_list的初始化 #include <stdio.h> #include "op_task.h" OpInfo OpTask::_op_info_list[] = { {"run", OpTask::op_task_run}, {"pause", OpTask::op_task_pause}, {"retry", OpTask::op_task_retry}, {"stop", OpTask::op_task_stop}, {"", NULL} }; int OpTask::op_task_run(const std::string &task_id) { printf("run task<%s> ...\n", task_id.c_str()); //do some running logic. return 0; } .....
//task_interface.h 文件,TaskInterface接口类 #ifndef _TASK_INTERFACE_H_ #define _TASK_INTERFACE_H_ #include <string> class TaskInterface { public: static int op_proxy(const std::string &task_id, const std::string &op_type); }; #endif //_TASK_INTERFACE_H_
//task_interface.cpp 文件,op_proxy的实现 #include <stdio.h> #include "task_interface.h" #include "op_task.h" int TaskInterface::op_proxy(const std::string &task_id, const std::string &op_type) { int ret = 0; OpInfo * info = &OpTask::_op_info_list[0]; while(info->_op_type != op_type && info->_op_type != "") info++; if (info->_op_fun == NULL) { printf("Unknown op_type: %s\n", op_type.c_str()); ret = -1; } else { ret = info->_op_fun(task_id); } return ret; }
测试代码就不贴了。
总体来说,这个方法还算优雅,如有其他思路,欢迎交流。
相关文章推荐
- 关于栈、堆、静态变量区的访问效率
- 关于指针定义的一些问题
- MinGW环境变量设置、CodeBlock添加额外的库
- websocket C/C++服务器应用
- #define do{}while(0)妙用
- 浅析pragma once与include guard
- Ubuntu14.04 学习二: C/C++环境搭建,执行第一个hello world
- 我所理解的makefile文件
- 对于VS中一些较严谨的(_s)函数如strcpy_s的第二个参数的问题
- 经典DP HDU 2084 数塔
- htonl,htons,ntohl,ntohs的详解
- Linux下VIM C/C++ IDE配置
- C++ Tips: 获取更精确的系统时间(Windows 系统)
- 多进程情况下文件句柄共享的问题
- linux中memset的正确用法
- bcopy和memcpy、bzero和memset、bcmp和memcmp的差别
- C/C++ 与函数有关的typedef用法
- 代码注释
- 你会解吗? ?+?+?=30 把下面数字填到框里 (1,3,5,7,9,11,13,15)
- C/C++学习笔记(二)