C ++ map <char,static =“”method =“”pointer =“”>?</char,>

时间:2013-05-26 11:20:58

标签: c++ function pointers methods static

我编写了一个非常基本的表达式解析器,我希望它是可扩展的,因此它可以解析用户定义的表达式类型。 例如,如果在解析时遇到字符<,我想创建一个用于解析以此字符开头的表达式的类的实例。

我有两个问题:

  1. 如何将字符与静态方法指针相关联?

    我想使用一个静态方法来返回类的新实例,因为我无法获得指向类constructror的指针。以下语法可能有误,但这就是想法:

    typedef static IValue * (*returnPtrIValue)();
    map<char, returnPtrIValue> ...
    
  2. 假设我有类A,类B扩展了类A,我可以初始化一个指向函数的指针,该函数将指针/ ref返回给A,指针指向一个返回指针/ ref的函数的指针。 a B是A?

    例如,我可以这样做:

    typedef A * (*returnPtrA)();
    B * func() { ... }
    returnPtrA foo = func;
    

5 个答案:

答案 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? 谢谢你的回答!