提问人:Johnson Jose 提问时间:6/25/2023 最后编辑:JeJoJohnson Jose 更新时间:6/25/2023 访问量:99
如何从类方法返回成员函数指针?
How to return a member function pointer from a class method?
问:
我正在尝试使用类似策略模式的东西,其中有两个不同的解析器Type1Parser
和Type2Parser
使用接口IParser
。
还有另一个类 ParsingText,我们有 2 个方法
setParser
:将设置解析器类型。getMethod
在解析器中返回一个方法。例如。格式
化或解析
。
#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;
}
我正在使用函数指针返回此类方法。但我做不到。 我不确定我在这里做错了什么?
答:
2赞
JeJo
6/25/2023
#1
我正在使用函数指针返回此类方法。但我做不到。我不确定我在这里做错了什么?
在 你正在尝试调用相应的成员函数,而不是返回它。正确的语法如下:getMethod
parseFunc getMethod(char o)
{
if (o == 'f') return &IParser::format; // ---> like this
else return &IParser::parse; // ---> like this
}
这将解决编译器错误。但是,您现在有下一期。为了调用指向成员函数的指针,您还需要一个相应的对象实例,该实例仅在类中私有可用。例如,一种解决方案是提供一个 getter,并用它调用指向 member 的指针。ParsingText
parser
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;
}
话虽如此,这可能不是您想要处理这种情况的方式。调用方端可能会更简洁,如果您返回了具有正确实例的被调用成员函数的包装版本。std::函数
在这里派上用场。IParser
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();
}
评论
getMethod
return &IParser::format;
IParser
parseFunc
std::function<std::string()>
getMethod
return [=]() { return parser->format(); };