函数向量_指针有不同的原型,我可以构建一个吗

Vector of fuctions_pointers whit different prototype, can i build one?

本文关键字:构建 我可以 一个 原型 指针 向量 函数      更新时间:2023-10-16

我正在为一个类调用virtual_machine做parser,我试图为它构建一个函数向量,但vm上的一些函数接受参数(不同数量/类型的参数(,我仍然可以将它们放在我的函数向量中,因为它们只有void(*f(((;

这是代码


class Virtual_Machine {
public:
/***/
void clear();
void pop();
void clear();
void assert(std::string const &value);
void push(eOperandType const &e, std::string const &str);
/***/
}
class Parser {
public:
/***/
void prepare();
void add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand);
private:
Virtual_Machine vm;
std::vector<std::string> command_no_arg;
std::vector<void (Virtual_Machine::*)()> func_no_arg;
/***/
};
void Parser::add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand)
{
command_no_arg.push_back(comand);
func_no_arg.push_back(f);
}
void Parser::prepare()
{
add_func_no_arg(&Virtual_Machine::dump,"dump");
add_func_no_arg(&Virtual_Machine::pop,"pop");
add_func_no_arg(&Virtual_Machine::clear,"clear");
}
void Parser::use_exemple()
{
// dump :
(vm.*(func_no_arg[0]))();
}

这是可以的,但现在我将转到kwon,如果可以将push((和assert((添加到我的函数向量中,我需要做什么?我想也许是模板,但我真的不明白是怎么回事

Daniel Jour的广泛链接答案显示了如何通过打包和boost::any来隐藏参数,这可能是一个更好的解决方案(但我并不完全理解(。作为替代方案,您可以使用变差函数,如下例所示。

请对我的代码持保留态度,我遇到了一些限制,我不是这个主题的专家:

  • 您无法通过...接收引用类型参数
  • 常量参数被提升为非常量参数(在我的测试中,const int被提升为int(
  • 我认为变异函数是一种安全风险。如果函数参数是由用户提供的,请检查/清除输入

下面是代码示例(请注意,我将Virtual_Machine::assert重命名为Virtual_Machine::vmassert,以使用<cassert>中的assert(:

#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <cstdarg>
class Virtual_Machine
{
private:
std::string name;
public:
Virtual_Machine(std::string n) : name(n) {}
void clear(size_t nargs, ...){std::cout << "Clear " << name << std::endl;};
void dump(size_t nargs, ...){std::cout << "Dump" << std::endl;};
void vmassert(size_t nargs, ...)
{
va_list args;
va_start(args, nargs);
assert(nargs == 1);
const std::string value(va_arg(args, std::string));
std::cout << "Assert " << value << std:: endl;
va_end(args);
}
void push(size_t nargs, ...)
{
va_list args;
va_start(args, nargs);
assert(nargs == 2);
const int e(va_arg(args, int));
const std::string str(va_arg(args, std::string));
std::cout << "Push " << e << ", " << str << std:: endl;
va_end(args);
}
};
class Parser
{
private:
Virtual_Machine vm;
std::vector<std::string> commands;
std::vector<void (Virtual_Machine::*)(size_t, ...)> funcs;
public:
Parser(std::string vm_name) : vm(vm_name) {}
void add_func(
void (Virtual_Machine::* f)(size_t, ...),
std::string command)
{
commands.push_back(command);
funcs.push_back(f);
}
void prepare()
{
add_func(&Virtual_Machine::clear, "clear");
add_func(&Virtual_Machine::dump, "dump");
add_func(&Virtual_Machine::vmassert, "assert");
add_func(&Virtual_Machine::push, "push");
}
void test()
{
(vm.*(funcs[0]))(0);
(vm.*(funcs[1]))(0);
(vm.*(funcs[2]))(1, std::string("abc"));
(vm.*(funcs[3]))(2, 42, std::string("def"));
}
};
int main()
{
Parser a("vm_a");
a.prepare();
a.test();
return 0;
}

我将所有Virtual_Machine成员函数的签名更改为(size_t nargs, ...),这样您就可以为所有可以用来声明Parser::funcs的函数提供一个统一的类型。现在,每个函数都必须使用参数数量和实际参数进行调用。