如何创建一个存储指向成员函数的指针的类 (C++)
Posted
技术标签:
【中文标题】如何创建一个存储指向成员函数的指针的类 (C++)【英文标题】:How to create a class that stores pointers to member functions (C++) 【发布时间】:2020-06-25 21:59:57 【问题描述】:我正在尝试创建一个类,该类存储指向其他类的成员函数的指针,并且可以从文本命令(如游戏控制台)执行。
根据此处找到的示例,我做了一些功能性的事情,它存储具有类似字符串的输入的成员。下面是我的实现。
文件: Command.hpp
#include <string>
#include <functional>
#include <unordered_map>
#include <string>
#include <iostream>
using namespace std;
class Command
public:
Command();
virtual ~Command();
void RegisterCommand(string command, function<void(const string&)> fun);
void Run(const string& command, const string& arg);
private:
unordered_map<string, function<void(const string&)>> functions;
;
文件: Command.cpp
Command::Command()
Command::~Command()
void Command::RegisterCommand(string command, function<void(const string&)> fun)
functions[command] = fun;
void Command::Run(const string& command, const string& arg)
functions[command](arg);
文件: main.cpp
#include "Command.hpp"
// function to register
void xyz_fun(const string& commandLine)
cout << "console output: " << commandLine << endl;
int main(int argc, char* argv[])
Command m_Cmd;
// Register function
m_Cmd.RegisterCommand("xyz_fun", xyz_fun);
// Run registered function
m_Cmd.Run("xyz_fun", "hello world.");
return EXIT_SUCCESS;
我的问题是如何实现一个通用类来存储具有未知输入参数(布尔值、整数、双精度值、字符串等)的成员。
例如,我可以这样做:
m_Cmd.RegisterCommand("xyz_fun2", xyz_function2);
然后打电话
m_Cmd.Run("xyz_fun2", false)
它有一个布尔参数而不是一个字符串。
提前感谢您的关注,欢迎提供任何帮助。
【问题讨论】:
如果Run
被错误的参数调用,你想发生什么?
“存储指向成员函数的指针的类” -- 这与您的代码不匹配。您的代码使用函数对象,而不是函数指针。 (我建议保留代码并更改问题的文本和标题。函数对象看起来更适合您的目标。)
你如何决定传递哪个参数值?例如,为什么m_Cmd.Run("xyz_fun2", false)
而不是m_Cmd.Run("xyz_fun2", true)
?
你好,JaMiT。非常感谢您的 cmets。也许我表达得不好。我的目标是实现一个类来处理用户传递的命令。它们是简单的命令,其中大多数的唯一目的是更改一些现有的标志。例如:随着程序的运行,用户可以输入命令来改变窗口大小。或者通过文本文件以自动方式执行此操作(类似于脚本)。
抱歉我的困惑问题。我是 C++ 的新手。
【参考方案1】:
代替
unordered_map<string, function<void(const string&)>> functions;
你可以的
union acceptable_types int i; char c; bool b; std::string* s; ... ;
unordered_map<string, function<void(acceptable_types)>> functions;
然后在调用函数时,只需将函数想要的值放入acceptable_types
类型的变量中即可。
如果一个函数想要使用一个特定的值,它应该只使用acceptable_types
union 的一个特定成员。
这是一个例子:
#include "Command.hpp"
void
my_bool_func (acceptable_types union_param)
bool bool_var = union_param.b;
// ...
// Use bool_var
// ...
void
my_string_func (acceptable_types union_param)
std::string string_var = *(union_param.s);
// ...
// Use string_var
// ...
int
main(int argc, char* argv[])
Command my_command;
acceptable_types union_var;
my_command.RegisterCommand("my_bool_func", my_bool_func);
my_command.RegisterCommand("my_string_func", my_string_func);
union_var.b = true;
my_command.Run("my_bool_func", union_var);
*(union_var.s) = "hello world.";
my_command.Run("my_string_func", union_var);
return 0;
【讨论】:
union
和指向 std::string
的原始指针都不是一个好主意。 union
特别不安全,尤其是在没有像这里那样进行类型跟踪/检查的情况下。在这种情况下,您应该推荐 std::variant
,因为它具有类型检查和值语义。
事实证明:您已经编写/推荐了未定义的行为。在这里执行*(union_var.s) = "hello world.";
是荒谬的,因为您从未在该地址分配任何std::string
,因此您无法取消引用它。你正在使用一个无效的、未初始化的指针,破坏了不属于你的内存。即使你确实分配了它,你也会建议新手用 C++ 编写 new
和 delete
,这可能是 99% 以上的 C++ 编码人员永远不需要的东西。以上是关于如何创建一个存储指向成员函数的指针的类 (C++)的主要内容,如果未能解决你的问题,请参考以下文章
C ++创建指向标头内所有公共静态成员函数的指针数组,然后使用它
C++,成员函数返回对包含指向 const 对象的指针的向量的 const 引用
C++ Visual Studio 非标准语法使用 '&' 创建指向成员的指针