Gun*_*iez 7 c c++ design-patterns coding-style
我认为问题很常见.您有一些输入字符串,并且必须根据字符串的内容调用函数.类似于字符串的switch().考虑命令行选项.
目前我正在使用:
using std::string;
void Myclass::dispatch(string cmd, string args) {
if (cmd == "foo")
cmd_foo(args);
else if (cmd == "bar")
cmd_bar(args);
else if ...
...
else
cmd_default(args);
}
void Myclass::cmd_foo(string args) {
...
}
void Myclass::cmd_bar(string args) {
...
}
Run Code Online (Sandbox Code Playgroud)
并在标题中
class Myclass {
void cmd_bar(string args);
void cmd_foo(string args);
}
Run Code Online (Sandbox Code Playgroud)
所以每个foo和bar我都要重复四次(4次).我知道我可以先将函数指针和字符串提供给静态数组,然后在循环中进行调度,保存一些if ... else行.但是有一些宏技巧(或预处理器滥用,取决于POV),这使得有可能以某种方式定义函数,同时让它自动更新数组?所以我只需要写两次,如果内联使用,可能只写一次?
我正在寻找C或C++的解决方案.
听起来你正在寻找Command模式
像这样的东西:
像这样创建一个地图
std::map<std::string, Command*> myMap;
Run Code Online (Sandbox Code Playgroud)
然后只需使用你的密钥执行这样的命令....
std::map<std::string, Command*>::iterator it = myMap.find(str);
if( it != myMap.end() ) {
it->second->execute()
}
Run Code Online (Sandbox Code Playgroud)
要注册命令,您只需执行此操作即可
myMap["foo"] = new CommandFoo("someArgument");
myMap["bar"] = new CommandBar("anotherArgument");
Run Code Online (Sandbox Code Playgroud)
小智 5
根据问题注释中的链接,基本解决方案是将字符串映射到某种函数调用.
要实际注册字符串 - >函数指针/仿函数对:
首先,有一个单身(shock!horror!)调度程序对象.我们称之为TheDispatcher - 它是a的包装器map<string,Func>,其中Func是你的函数指针或函子类型.
然后,有一个注册类:
struct Register {
Register( comst string & s, Func f ) {
TheDispatcher.Add( s, f );
}
};
Run Code Online (Sandbox Code Playgroud)
现在,在您的个人编译单元中,您可以创建静态对象(shock!horror!):
Register r1_( "hello", DoSayHello );
Run Code Online (Sandbox Code Playgroud)
将创建这些对象(假设代码不在静态库中)并将自动向TheDispatcher注册.
在运行时,您在TheDispatcher中查找字符串并执行相关的函数/函子.
丑陋的宏观解决方案,这正是您所要求的。请注意,它不会自动注册,但它确实会保持某些内容同步,并且如果您仅添加到映射而不是源文件中的函数,也会导致编译错误。
映射.h:
// Note: no fileguard
// The first is the text string of the command,
// the second is the function to be called,
// the third is the description.
UGLY_SUCKER( "foo", cmd_foo, "Utilize foo." );
UGLY_SUCKER( "bar", cmd_bar, "Turn on bar." );
Run Code Online (Sandbox Code Playgroud)
解析器.h:
class Myclass {
...
protected:
// The command functions
#define UGLY_SUCKER( a, b, c ) void b( args )
#include Mappings.h
#undef UGLY_SUCKER
};
Run Code Online (Sandbox Code Playgroud)
解析器.cpp:
void Myclass::dispatch(string cmd, string args) {
if (cmd == "")
// handle empty case
#define UGLY_SUCKER( a, b, c ) else if (cmd == a) b( args )
#include Mappings.h
#undef UGLY_SUCKER
else
cmd_default(args);
}
void Myclass::printOptions() {
#define UGLY_SUCKER( a, b, c ) std::cout << a << \t << c << std::endl
#include Mappings.h
#undef UGLY_SUCKER
}
void Myclass::cmd_foo(string args) {
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5494 次 |
| 最近记录: |