【问题标题】:C++ map<char, static method pointer>? [duplicate]C++ map<char,静态方法指针>? [复制]
【发布时间】:2013-05-21 10:59:11
【问题描述】:

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

我有两个问题:

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

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

    typedef static IValue * (*returnPtrIValue)();
    map<char, returnPtrIValue> ...
    
  2. 假设我有 A 类,并且 B 类扩展 A 类,我可以初始化一个指向函数的指针,该函数返回指向 A 的指针/引用,并使用指向返回指向 B 的指针/引用的函数的指针,因为 B 是一个A?

    例如,我可以这样做:

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

【问题讨论】:

  • 解析是由所有对象共享的class 方法/函数完成的,那为什么每次都要创建一个类的新实例呢?只需存储与&lt; 关联的类的全局对象并使用其方法即可。
  • 因为在我设计解析器的方式中,表达式是一个从一段字符串中解析出自身的对象。
  • 如果您有兴趣编写解析/词法分析器,我建议您查看libclang,例如stackoverflow.com/questions/14509120/any-tutorial-on-libclang

标签: c++ function pointers methods static


【解决方案1】:

1) 只需从 typedef 中删除 static,“静态方法”就像一个简单的函数(仅在类范围内声明)。

2) 这似乎是合法的,但不幸的是我得到了一个编译器错误:

error: invalid conversion from 'B* (*)()' to 'A* (*)()'

看来function pointers don't support covariant return types...

【讨论】:

  • 谢谢,我看看能不能换个方式。
【解决方案2】:

这段代码应该回答你的问题,即使不完全是。事实上,我通过使用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 反射,注定会出现性能问题。看看能不能细化一下。

【讨论】:

  • 谢谢,我看看能不能适应我的工作。
  • 请注意它使用了一些非重要的 C++11 功能。可以方便地降级。
【解决方案3】:

1:从 typedef 中删除 static,例如:

typedef IValue * (*returnPtrIValue)();

然后可以将指向静态成员函数的指针分配给该类型的变量(或放入映射中),例如:

returnPtrIValue fun = &SomeClass::somestaticfun;

这是你要求的吗?

2:一般来说 - 没有。至少不是以类型安全的方式。协方差在 C++ 中不起作用。

如果您真的想要这样做,您可以使用 reinterpret_cast 或使用 union 进行一些骇客操作,但这可能取决于编译器,我不建议这样做(我如果你确实想要这个,可以给你一些提示)。

更新:Here is the really good article,它解释了如何在 C++ 中借助(成员)函数指针在 C++ 中实现委托。它深入研究了这个问题,我发现它的前半部分是 C++ 中(成员)函数指针以及如何使用它们的很好的参考/解释。如果您有兴趣了解它们在 C++ 中的工作原理,我建议您查看一下。

【讨论】:

  • 谢谢,1 是的,这就是我所需要的,对于 2,我会看看是否还有其他方法。
  • @Virus721 很酷,如果您需要关于 2 的提示,请在此处评论。还可以查看我帖子中的更新 - 可能对您有用。
  • 谢谢,但我在这里找到了我需要的东西:stackoverflow.com/questions/4007382/…:D
【解决方案4】:

如果你使用的是 C++11,你可以试试这样:

#include <map>
#include <functional>
...
std::map<char, std::function<parser*()>> m;
m['a'] = []{return new parser_for_a;};

这样你就不需要任何静态方法了。

【讨论】:

  • 谢谢,看起来很优雅,但我将在使用 Visual Studio 2005 的移动设备上使用它,我不确定它是否能处理 C++11 的东西。
  • 是的,你至少需要 vs2010。
【解决方案5】:

这个帖子帮助我做我想做的事:How to create class objects dynamically? 感谢您的回答!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-05
    • 2016-07-21
    • 2013-06-14
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多