C++如何替换构造函数开关?

2023-12-11

我想用更优雅的东西替换大开关。

class Base
{
public:
  Base(void*data, int size);
  virtual void Something() = 0;
}
class A : public Base
{
public:
  A(void*data, int size) : Base(data, size) {}
  void Something() override;
}
class B : public Base
{
public:
  B(void*data, int size) : Base(data, size) {}
  void Something() override;
}
...

{
  char c = input;
  switch (c)
  {
    case 'a':
    {
      A obj(data, size);
      obj.Something();
      break;
    }
    case 'b':
    {
      B obj(data, size);
      obj.Something();
      break;
    }
    ...
  }
}

正如您在示例类中看到的那样A and B与外面没有什么不同。 我想找到一种方法来消除该开关,只需实例化正确的类并在其上调用相同的方法,在我的真实代码中,该开关超过 1000 行长,并且有更多的类,但我找不到任何方法摆脱它。

在实际代码中,我有 2 个枚举而不是字符,并且还有更多开关,但我希望问题很清楚。

我的想法之一是在基类上使用模板,但我没有找到一种方法如何在没有那个巨大开关的情况下实例化正确的子项。

EDIT我从网络接收数据包并想要解析它并处理它。这些课程a, b, ...没有任何私有或公共成员,基类只有指向日期的原始指针和指向响应套接字的共享指针(也来自构造函数)。

我希望编译器为我生成该开关模板?或其他一些机制来删除重复的源代码。现在它仍处于测试阶段,但它每秒处理大约 1000 个数据包,所以我不想删除交换机并损失堆上分配和释放的性能。


找到一个实现static_for,而且它本身很简单:

using list = std::tuple<A, B, C, D, E, F, G, ...>;

const auto n = c - 'a';
static_for<std::tuple_size<list>()>([&](auto N){
    if (n != N)
        return;
    using T = std::tuple_element_t<list, N>;
    T obj(data, size);
    obj.Something();
});

进一步考虑:

  1. 如果它们都具有相同的多态接口,您可以决定仅使用它来创建对象。

  2. 如果你的范围内有漏洞,if constexpr and std::is_same是你的朋友。

  3. 使用一些专用的类型列表类型可能比std::tuple,但这在紧要关头有效。

一个未经修饰的、快速且肮脏的示例实现static_for():

template <std::size_t Is, class F>
void static_for_impl(F&& f, std::index_sequence<Is...>) {
    f(std::integral_constant<std::size_t, Is>()), ...;
}

template <std::size_t N, class F>
void static_for(F&& f) {
    static_for_impl(f, std::make_index_sequence<N>());
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++如何替换构造函数开关? 的相关文章

  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • 将 Word 文档另存为图像

    我正在使用下面的代码将 Word 文档转换为图像文件 但是图片显得太大 内容不适合 有没有办法渲染图片或将图片保存到合适的尺寸 private void btnConvert Click object sender EventArgs e
  • 在 C 中初始化变量

    我知道有时如果你不初始化int 如果打印整数 您将得到一个随机数 但将所有内容初始化为零似乎有点愚蠢 我问这个问题是因为我正在评论我的 C 项目 而且我对缩进非常直接 并且它可以完全编译 90 90 谢谢 Stackoverflow 但我想
  • 具有交替类型的可变参数模板参数包

    我想知道是否可以使用参数包捕获交替参数模式 例如 template
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • 如何在 Xaml 文本中添加电子邮件链接?

    我在 Windows Phone 8 应用程序中有一些大文本 我希望其中有电子邮件链接 例如 mailto 功能 这是代码的一部分
  • Azure 辅助角色“请求输入之一超出范围”的内部异常。

    我在辅助角色中调用 CloudTableClient CreateTableIfNotExist 方法 但收到一个异常 其中包含 请求输入之一超出范围 的内部异常 我做了一些研究 发现这是由于将表命名为非法表名引起的 但是 我尝试为我的表命
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 为什么 std::strstream 被弃用?

    我最近发现std strstream已被弃用 取而代之的是std stringstream 我已经有一段时间没有使用它了 但它做了我当时需要做的事情 所以很惊讶听到它的弃用 我的问题是为什么做出这个决定 有什么好处std stringstr
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 使用管道时,如果子进程数量大于处理器数量,进程是否会被阻塞?

    当子进程数量很大时 我的程序停止运行 我不知道问题是什么 但我猜子进程在运行时以某种方式被阻止 下面是该程序的主要工作流程 void function int process num int i initial variables for
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 使用 .NET Process.Start 运行时挂起进程 - 出了什么问题?

    我在 svn exe 周围编写了一个快速而肮脏的包装器来检索一些内容并对其执行某些操作 但对于某些输入 它偶尔会重复挂起并且无法完成 例如 一个调用是 svn list svn list http myserver 84 svn Docum
  • 当从finally中抛出异常时,Catch块不会被评估

    出现这个问题的原因是之前在 NET 4 0 中运行的代码在 NET 4 5 中因未处理的异常而失败 部分原因是 try finallys 如果您想了解详细信息 请阅读更多内容微软连接 https connect microsoft com

随机推荐

  • 如何使用 Spring MVC 从 url 下载文件?

    我的 jsp 中有这样的下载选项 a href img src images download gif alt Download border 0 align right 上面的 url 是文件的位置 名称是文件名 单击jsp中的下载选项时
  • awk每列n条数据的平均值

    使用 awk 将值存储在数字列表中 提供使用 awk 对列中每组 3 个点进行平均的解决方案 如何将其扩展到保持格式的无限数量的列 例如 2457135 564106 13 249116 13 140903 0 003615 0 00344
  • 检测并修复 JavaScript 中的循环引用

    鉴于我在一个大型 JavaScript 对象中有一个循环引用 我尝试JSON stringify problematicObject 浏览器抛出 类型错误 将循环结构转换为 JSON 这是预期的 那我想找到这个循环引用的原因 最好使用Chr
  • git 警告“无法访问权限被拒绝”在 .gitignore 目录上

    我的一个名为 Database 的目录中有一个名为 gitignore 的子目录 我希望 git 忽略它 所以我将其列在我的 gitingore 文件中 gitignore Bb in Dd ebug Rr elease gitignore
  • 在视口组件上使用 JScrollPane 鼠标侦听器

    我有一个JScrollPane可以设置其视口View到一系列不同的面板 我想在单击其视口中的任何其他组件时获取 JScrollPane 组件 如果我添加一个MouseListener对于 JScrollPane 当我直接单击窗格边框时 它会
  • 在 VBA 中下载文件并存储

    我需要下载从 REST 搜索中获得的文件 网址如下 由于隐私原因 我需要对其进行编辑 该文件应该是 Nastran 计算的结果 可以通过简单的文本编辑器查看 扩展名是 pch 比较大 21mb 如何在 VBA 中实现呢 首先 链接不起作用
  • 按返回类型重载函数?

    为什么更主流的静态类型语言不支持按返回类型重载函数 方法 我想不出有什么可以做到的 它看起来并不比支持参数类型重载有用或合理 怎么人气这么低 与其他人所说的相反 按返回类型重载is可能和is由一些现代语言完成 通常的反对意见是在类似的代码中
  • 自定义日期时间格式

    我需要将日期格式化为 2010 04 21 11 35 22 440 谁能帮我 问题是我看到的是 2009 06 15T13 45 30 0900000 或 2008 03 09 16 05 07Z 但不是我正在寻找的那个 谢谢 strin
  • 删除插件类中定义的操作

    我正在开发一个电子商务主题 我已经安装了WooCommerce PayPal 结账支付网关付款插件 我想更改此结帐按钮的位置 我尝试remove action显示结帐按钮 但它不起作用 在这种情况下如何删除操作 Hook in plugin
  • 需要在c#中进行double类型的枚举

    如何创建 double 类型的枚举 是否可能或者我必须创建某种集合和哈希 你不能把它变成一个枚举 http msdn microsoft com en us library y94acxy2 aspx 可能性之一 public static
  • 为什么 XmlPullParser 传递两个 START_DOCUMENT 事件?

    在 Android 应用程序中我有一个XmlPullParser XmlResourceParser xrp c getResources getXml rid 正如您所看到的 它来自 Android 二进制 XML 资源 并且它提供的前两
  • 检测 NSString 的语言

    有人告诉我关于 Cocoa 中的语言识别类 有人知道它是哪一个吗 This is not在职的 NSSpellChecker spellChecker NSSpellChecker sharedSpellChecker spellCheck
  • 无法在 VC++ 中使用 std::cout 打印出 argv[] 值

    这是我在该网站上的第一个问题 尽管我来这里参考已经有一段时间了 我知道 argv 0 存储程序的名称 其余命令行参数存储在剩余的 argv k 槽中 我还了解 std cout 将字符指针视为空终止字符串并打印该字符串 下面是我的程序 in
  • 如何与主应用程序一起开发另一个子模块。 [作曲家,PHP]

    我知道 git 子模块是如何工作的 以及我们如何使用它 现在我所处的情况是 主应用程序依赖于许多其他作曲家软件包 并且我必须制作和开发一个与主项目 某种库 分开的另一个小软件包 那么我如何才能将这个小包与主项目一起开发 而不使其成为单独的项
  • 反应本机启动画面获取“React/RCTBridgeModule.h”文件未找到

    我使用以下命令启动了一个新的反应本机应用程序 react native init myApplication 我从启动画面开始 所以我使用了这个库反应本机启动画面 我使用以下命令链接该库以生成本机代码 react native link r
  • 如何将标准容器作为字段添加到 OMNet++ 消息中?

    我正在尝试创建一个简单的消息定义包含一个使用实现的字段std vector 根据OMNet 5 5 手册第 1 章6秒 8 1 这看起来很简单 However I m using OMNet 6 0pre6 I can t figure o
  • 单击退出按钮时未处理 Win32Exception - Visual Basic

    我正在使用 Microsoft Visual Studio 2010 32 位高级版 Microsoft Visual Basic 2010 构建表单 当我编译代码时没有任何错误 但是每当我单击退出按钮时 它都会显示以下消息 Win32Ex
  • blackberry os 7 模拟器未在我的系统上加载

    我已经安装了blackberry os 7模拟器 9900 9930 9850 当我打开模拟器时 会显示黑莓加载屏幕 但没有完全加载 长时间显示如下图所示 我删除了位于的 dmp 文件 C Program Files Research In
  • 使用 LINQ 获取平均值

    希望有人可以帮助我使用 LINQ 语法来计算平均值 例如 我有以下 LINQ 查询 var rates from rating in ctx Rates where rating Id Id select new UserId rating
  • C++如何替换构造函数开关?

    我想用更优雅的东西替换大开关 class Base public Base void data int size virtual void Something 0 class A public Base public A void data