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

2024-01-10

我正在为一个名为 virtual_machine 的类做一个解析器,我正在尝试为其构建一个函数向量,但是 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]))();
}

没关系,但现在我想知道是否可以将 Push() 和 assert() 添加到我的函数向量中,我需要做什么?我想也许是模板,但我真的不明白如何


Daniel Jour 的广泛链接答案 https://stackoverflow.com/a/32041381/2546289展示了如何通过打包和隐藏参数来实现boost::any并且可能是一个更好的解决方案(但我没有完全理解它)。 作为替代方案,您可以使用可变参数函数 https://en.cppreference.com/w/cpp/utility/variadic如下例所示。

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

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

这是代码示例(请注意,我重命名为Virtual_Machine::assert to Virtual_Machine::vmassert to use assert from <cassert>):

#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。现在必须使用参数数量和后跟实际参数来调用每个函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有不同原型的函数指针向量,我可以构建一个吗? 的相关文章

  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐