c++ 如何从类方法返回成员函数指针?

2ul0zpep  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(161)

我试图使用类似于strategy pattern的东西,其中有两个不同的解析器**Type1ParserType2Parser使用接口IParser。还有另一个类ParsingText**,其中我们有2个方法
1.setParser:这将设置解析器类型。
1.getMethod返回解析器中的方法。例如formatparse

#include <iostream>
#include<vector>
#include<string>
using namespace std;

class IParser 
{
public:
    virtual ~IParser() = default;
    virtual string format() = 0;
    virtual string parse() = 0;
};

class Type1Parser :public IParser 
{
public:
    string format() override 
    {
        cout << " Formatting 1";
        return string();
    }
    string parse() override
    {
        cout << " Parsering 1";
        return string();
    }
};

class Type2Parser :public IParser 
{
public:
    string format() override 
    {
        cout << " Formatting 2";
        return string();
    }
    string parse() override 
    {
        cout << " Parsering 2";
        return string();
    }
};

typedef string(IParser::* parseFunc)();
class ParsingText
{
    IParser* parser;

public:
    void setParser(int p) 
    {
        if (p == 1) parser = new Type1Parser();
        if (p == 2) parser = new Type2Parser();
    }

    parseFunc getMethod(char o) 
    {
        if (o == 'f') return parser->format;
        else return parser->parse;
    }
};

int main() 
{
    ParsingText* pt = new ParsingText();

    pt->setParser(1);
    parseFunc myMethod = pt->getMethod('f');
    *myMethod();
    return 0;
}

我使用一个函数指针来返回这个类方法。但我不能这样做。我不知道我做错了什么?

a64a0gku

a64a0gku1#

我使用一个函数指针来返回这个类方法。但我做不到我不知道我做错了什么?
getMethod中,你试图调用相应的成员函数,而不是返回它。正确的语法如下:

parseFunc getMethod(char o)
{
    if (o == 'f') return &IParser::format;  // ---> like this
    else          return &IParser::parse;   // ---> like this
}

这将解决编译器错误。不过,你现在有下一个问题。为了实现call the pointer to member function,你还需要一个相应的对象示例,它只能在ParsingText类中私有地使用。一种解决方案是为parser示例提供一个getter,并使用它调用指向成员的指针。

class ParsingText 
{
    // Use smart pointer rather than raw pointer(ex. std::unique_ptr)
    IParser* parser{ nullptr };
public:

    //  MEMORY LEAKS in setParser() !!!

    parseFunc getMethod(char o)
    {
        if (o == 'f') return &IParser::format;
        else          return &IParser::parse;
    }
    // Provided a getter for IParser
    IParser* getParser() { return parser; }
};

int main() 
{
    // Use smart pointer rather than raw pointer(ex. std::unique_ptr)
    auto pt{std::make_unique<ParsingText>()};

    pt->setParser(1);

    parseFunc myMethod = pt->getMethod('f');
    
    if (auto parser = pt->getParser())
    {
        (parser->*myMethod)(); // invoke with the Parser instance
        // or since C++17, from  <functional> header
        // std::invoke(myMethod, parser);
    }
    return 0;
}

See live demo in godbolt.org
话虽如此,这可能不是你想要的处理这个案子的方式。如果您返回了被调用的成员函数的 Package 版本和正确的IParser示例,那么调用者端可能会更干净。std::function在这里派上用场。

class ParsingText 
{
    // Use smart pointer rather than raw pointer(ex. std::unique_ptr)
    IParser* parser{ nullptr };
public:
    //  MEMORY LEAKS in setParser()!!!

    std::function<std::string()> invokeMethod(char o)
    {
        if (o == 'f' && parser) return [this] {return parser->format(); };
        else if (parser)        return [this] {return parser->parse(); };
        else return {}; // or some error handling
    }
};

int main() 
{
    // Use smart pointer rather than raw pointer(ex. std::unique_ptr)
    auto pt{std::make_unique<ParsingText>()};
    pt->setParser(1);

    auto callable = pt->invokeMethod('f'); // invoke like this
    callable();
}

See live demo in godbolt.org

相关问题