事先道歉可能含糊不清的标题,我能想出最好的。
我有以下C ++和文本文件:
cpp文件:
class Test
{
int var1;
int var2;
public:
bool set_var1();
bool set_var1();
bool set(string var_name);
void process_file();
}
文本文件:
var1 value1
var2 value2
目标 - 在process_file()中,读取/解析文本文件,并为文件中的每个varX调用相应的set_varX()。
一个选项,在函数set()中,将var_name与“var1”/“var2”/ etc进行比较,以及 调用相应的set_varX()。我对这种方法的问题更多 行被添加到文本文件中,代码变得......丑陋,带有长“if-else” set()中的代码块。
另一个选项,创建一个静态地图 “var1”set_var1() “var2”set_var2()
set()将遍历地图,并在字符串比较匹配时调用相应的func_ptr。此选项需要维护地图结构。
虽然我更喜欢第二个选项,但是随着测试文件的增加,代码更改的更少,是否还有其他选择。只是大声思考,在set()中,我可以取字符串var_name,并在pre_之前调用set_var_name(),基本上以某种方式避免字符串比较,这在上述两种情况下都可以完成。我的直觉是,在C ++中,在运行时不可能做到
谢谢你, 艾哈迈德。
答案 0 :(得分:2)
听起来你问的是反射,这不是C ++的一个特性,所以这是不可能的。正如您所指出的,该问题有解决方案,但所有这些都涉及到字符串名称到函数的映射,您必须自己构建/维护该映射。语言不适合你。
答案 1 :(得分:0)
您可以通过创建var1,var2 ..自注册类型来改进选项2。新关键字不会导致代码更改,只会导致新类型。因此,地图必须是某种全球对象,单身等等。
一个非常简单的例子:
struct Setter
{
virtual ~Setter() = default;
virtual void Process(std::string content) const = 0;
};
class SetterMap
{
public:
bool RegisterSetter(std::string keyword, std::unique_ptr<Setter> setter) {
setters[keyword] = move(setter);
return true;
}
const Setter& GetSetter(const std::string& keyword) const {
return *(setters.at(keyword));
}
private:
std::map<std::string, std::unique_ptr<Setter>> setters;
};
inline SetterMap& GetSetterMap() {
static SetterMap map;
return map;
}
定义并注册一些setter:
struct Var1 : Setter {
void Process(std::string content) const override {
}
};
namespace {
bool var1registered = GetSetterMap().RegisterSetter(
"var1", std::make_unique<Var1>());
}
struct Var2 : Setter {
void Process(std::string content) const override {
}
};
namespace {
bool var2registered = GetSetterMap().RegisterSetter(
"var2", std::make_unique<Var2>());
}
使用setter map:
int main()
{
std::string line = "var1: blablab";
GetSetterMap().GetSetter("var1").Process(line);
}
答案 2 :(得分:0)
根据您的需要,您可以考虑嵌入Lua并将文本文件的语法更改为:
test.var1 = 1234
test.var2 = 42
这里,test
将是一个全局Lua表,您可以从C ++端实例化并使用lua_setmetatable()
分配metatable。 metatable将有一个__newindex
方法,如here所述。如果您熟悉Python,这有点像提供__setattr__
元方法,即它拦截不存在的字段的分配并执行一些用户指定的魔法。
你的案例中的'技巧'是在Lua中创建一个metatable,它将var1
的{{1}},var2
等字段的访问重新路由到{{3}包装器,用于设置基础test
对象上的相应字段。之后,您只需使用lua_CFunction
“运行”该文件即可。
一个快速肮脏的例子(针对Lua 5.1.5测试)说明了这个想法的要点如下。 (由于使用了原始字符串文字,因此需要使用Test
进行编译。)
如果您的需求非常特定/有针对性,这种方法肯定是矫枉过正的。但是,如果您希望/需要在您的应用程序中编写脚本,无论如何,嵌入Lua是一个很好的解决方案。
注意:严格必需使用单独的表格(例如,示例中为-std=c++11
)。 Lua将全局变量存储在名为test
的表中,因此您可以为_G
设置元表。但是,这样做有点像黑客;它使示例更难以遵循,并将限制在宿主应用程序中使用Lua的其他一些方法。
_G