我编写了一个非常基本的表达式解析器,我希望它是可扩展的,因此它可以解析用户定义的表达式类型。
例如,如果在解析时遇到字符<
,我想创建一个用于解析以此字符开头的表达式的类的实例。
我有两个问题:
如何将字符与静态方法指针相关联?
我想使用一个静态方法来返回类的新实例,因为我无法获得指向类constructror的指针。以下语法可能有误,但这就是想法:
typedef static IValue * (*returnPtrIValue)();
map<char, returnPtrIValue> ...
假设我有类A,类B扩展了类A,我可以初始化一个指向函数的指针,该函数将指针/ ref返回给A,指针指向一个返回指针/ ref的函数的指针。 a B是A?
例如,我可以这样做:
typedef A * (*returnPtrA)();
B * func() { ... }
returnPtrA foo = func;
答案 0 :(得分:3)
1:从typedef中删除static
,例如:
typedef IValue * (*returnPtrIValue)();
然后可以将指向静态成员函数的指针分配给该类型的变量(或放入映射),如:
returnPtrIValue fun = &SomeClass::somestaticfun;
这是你要的吗?
2:一般来说 - 没有。至少不是以类型安全的方式。协方差在C ++中不起作用。
如果真的想要这样做,你可以使用reinterpret_cast
或对联盟做一些hackery,但这可能是编译器依赖的,我不建议这样做(无论如何你都想要这个,我可以给你一些提示。)
更新: Here is the really good article,它解释了如何借助C ++中的(成员)函数指针在C ++中实现委托。它深入研究了这个问题,我发现它的前半部分是C ++中(成员)函数指针的非常好的参考/解释以及如何使用它们。如果您有兴趣了解它们如何在C ++中工作,我建议您查看它。
答案 1 :(得分:2)
1)只需从typedef中删除static
,“静态方法”就像一个简单的函数(仅在类的范围内声明)。
2)这似乎是合法的,但遗憾的是我收到了编译错误:
error: invalid conversion from 'B* (*)()' to 'A* (*)()'
似乎是function pointers don't support covariant return types ......
答案 2 :(得分:1)
如果你正在使用C ++ 11,你可以尝试这样的事情:
#include <map>
#include <functional>
...
std::map<char, std::function<parser*()>> m;
m['a'] = []{return new parser_for_a;};
这样您就不需要任何静态方法。
答案 3 :(得分:0)
即使不完全,此代码也应该回答您的问题。事实上,我使用virtual
调用解决了一些问题(注意:性能问题)。
#include <iostream>
#include <map>
struct parse_result {
// something here
};
class parser {
public:
virtual parse_result parse() = 0;
};
class parser1 : public parser {
public:
parse_result parse() {
// something here
std::cout << "Called parser1::parse()" << std::endl;
return parse_result();
}
};
class parser2 : public parser {
public:
parse_result parse() {
// something here
std::cout << "Called parser2::parse()" << std::endl;
return parse_result();
}
};
static parser1* make_parser1() {
return new parser1();
}
static parser2* make_parser2() {
return new parser2();
}
typedef parser* (*parser_factory_method)();
int main() {
std::map<char, parser_factory_method> parsers;
parsers.insert(std::make_pair('1', (parser_factory_method) make_parser1));
parsers.insert(std::make_pair('2', (parser_factory_method) make_parser2));
for (auto entry : parsers) {
std::cout << "Calling parser for " << entry.first << std::endl;
parser_factory_method pfm = entry.second;
parser* p = pfm();
p->parse(); // parse_result is ignored here, but can be used as needed
delete p;
}
return 0;
}
请注意解析器的我不喜欢此设计。它以某种方式模仿Java反射,注定会出现性能问题。看看你是否可以改进它。
答案 4 :(得分:0)
这个帖子帮我做了我想做的事:How to create class objects dynamically? 谢谢你的回答!