多个派生类的dynamic_cast

2024-03-02

我有一个基类和n派生类。我想实例化一个派生类并将其发送到一个接收基类作为参数的函数。在函数内部,我通过使用dynamic_cast找到了它是哪种类型的派生类,但我不想使用几个if-else语句。相反,我想知道是否有一种方法可以找出它是哪个派生类,以便对其进行强制转换。 这里我留下我的代码作为示例。

class animal{
   public: 
          virtual ~animal() {}
          int eyes;

  };

class dog: public animal{
   public:
         int legs;
         int tail;
  };

class fish: public animal{
   public:
         int mostage;
  };

void functionTest(animal* a){
  if(dynamic_cast<fish*>(a) != NULL){
                             do_something();
                             }
  else if(dynamic_cast<dog*>(a) != NULL){
                              do_something();
                              }
 };

我想对此有一个更通用的方法。类似于dynamic_cast(a)。谢谢你!


如果您需要在几分钟内演示某些内容,那么对于快速草稿来说这样做是很棒的,但通常您会尝试避免以这种方式使用dynamic_cast - 如果在错误的地方使用它可能会导致极高的维护成本。有多种模式可用,例如简单的方法重载、Visitor http://en.wikipedia.org/wiki/Visitor_pattern模式,或虚拟的“GetType”函数(可以使用奇怪的重复模板模式 http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern,如果您喜欢图案)。

我将列出所有 3 种方法。第一个是迄今为止最简单、最容易使用的。另外两个的优点是它们都将做什么的决定转移到代码的不同部分,这可能是一个巨大的好处(或缺点)。

让我们假设这就是您想要做的:

void functionTest(animal* a)
{
    if(dynamic_cast<fish*>(a) != NULL)
        blub();
    else if(dynamic_cast<dog*>(a) != NULL)
        bark();
};

简单的虚函数方法:

class animal {
public: 
    virtual ~animal() {}
    virtual void do_something() = 0;
    int eyes;    
};

class dog : public animal {
public: 
    virtual void do_something() { bark(); } // use override in C++11
    int legs;
    int tail;
};

class fish: public animal {
public: 
    virtual void do_something() { blub(); } // use override in C++11
    int mostage;
};

void functionTest(animal* a)
{
   if (a) a->do_something();
};

访客方式:

class IVisitor {
public:
   ~IVisitor(){}
   virtual void visit(const fish&){}
   virtual void visit(const dog&){}
   virtual void visit(const animal&){}
};

class animal {
public: 
    virtual ~animal() {}
    virtual void accept(IVisitor& visitor) = 0; 
    int eyes;
};

class dog : public animal {
public: 
    virtual void accept(IVisitor& visitor) { visitor.visit(*this); }  // use override in C++11
    int legs;
    int tail;
};

class fish : public animal {
public: 
    virtual void accept(IVisitor& visitor) { visitor.visit(*this); }  // use override in C++11
    int mostage;
};

class MyVisitor : public IVisitor {
public:
   virtual void visit(const fish&) { blub(); } // use override in C++11
   virtual void visit(const dog&) { bark(); }  // use override in C++11   
};

void functionTest(animal* a)
{
    if (a)
    {
        MyVisitor v;
        a->accept(v);
    }
};

GetType 方法,具有CRTP http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern spice:

class animal {
public: 
    virtual ~animal() {}
    virtual const type_info& getType() const = 0; // careful. typeinfo is tricky of shared libs or dlls are involved
    int eyes;    
};

template <class T>
class BaseAnimal : public animal {
    // these are C++11 features. Alternatives exist to ensure T derives from BaseAnimal.
    static_assert(std::is_base_of<BaseAnimal,T>(,"Class not deriving from BaseAnimal");// C++11

    virtual const type_info& getType() const { return typeid(T); }    
};

class dog : public BaseAnimal<dog> {
public:
    int legs;
    int tail;
};

class fish : public BaseAnimal<fish> {
public:
    int mostage;
};

void functionTest(animal* a)
{
   if (!a)
      return;
   if (a->getType() == typeid(fish))
        blub(); 
   else if (a->getType() == typeid(dog))
        bark();
};

请注意,您应该将上述示例视为伪代码。为了获得最佳实践,您需要查找模式。此外,奇怪的重复模板模式也可以在第二种方法中使用,或者可以轻松地从第三种方法中删除它。这只是为了在这些情况下方便。

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

多个派生类的dynamic_cast 的相关文章

  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • React hooks - useState() 不会使用新状态更新重新渲染 UI

    我正在尝试新的 React Hooks 但我有点卡住了 因为更新本地状态时 UI 没有更新 这是我的代码 import React useState useEffect from react import Post from Post im
  • runas 不允许复杂的参数?

    我有一个应用程序 我试图在 Windows 7 和 Windows XP 瘦客户端上运行提升 但我似乎无法正确获取 runas exe 命令行 我知道我需要其中的反斜杠转义字符 以便 runas 正确解释空格 当将 run 作为已用反斜杠转
  • 如何将原始数据传递给asp.net core中间件

    我需要将一些数据传递到 ASP NET CORE 中间件 例如如果这是一个字符串列表 您是否使用与传递服务相同的机制 例如将其作为参数添加到 Invoke 方法中并向 DI 注册 如果是这样 您如何进行原始类型的注册 例如字符串列表 它必须
  • 在 R 中轻松输入相关矩阵

    我现在正在运行一个 R 脚本 当前使用 3 个相关变量 我想添加第四个 并且想知道是否有一种简单的方法来输入矩阵数据 特别是对于相关矩阵 一些类似Matlab的技术在R中输入相关矩阵 3x3或4x4 而不需要线性我一直在使用矩阵重塑 在 M
  • 如何让 prettier 打破所有联合类型?

    我要这个 type SomeType Variant1 Variant2 始终格式化为 type SomeType Variant1 Variant2 不管是否溢出指定的列宽 如果您需要对格式进行一定程度的控制 那么您可能不是 Pretti
  • matplotlib 中的直方图,x 轴上的时间

    我是 matplotlib 1 3 1 2 的新手 我找不到合适的起点 我想用 matplotlib 在直方图中绘制点随时间的分布 基本上我想绘制日期出现的累积总和 date 2011 12 13 2011 12 13 2013 11 01
  • 在 Java 中创建哈希的标准方法

    问题是关于在 Java 中创建哈希的正确方法 假设我有一个积极的BigInteger我想从中创建哈希的值 让我们假设下面的实例messageDigest是一个有效的实例 SHA 256 public static final BigInte
  • Docker 中的 Cassandra 无法从外部连接

    大家好 我是 Docker 和 Cassandar 这个词的新手 我从计算机连接到 Docker 中的 Cassandra 时遇到问题 我运行容器 Cassandra 我看到暴露的 ips 和端口是 192 168 99 100 9042
  • Android 无法通过互联网从 PC 服务器接收 UDP 数据

    我目前正在探索用Java 进行UDP 数据包传输 以在Android 上创建多人游戏 我使用通常的 127 0 0 1 成功地在 Nexus 4 内交换数据包 并且还成功地在本地网络中的 PC 服务器和 Android 客户端之间交换数据包
  • 使用 Maven 创建 META-INF/services 文件

    有没有办法使用 Maven 在 META INF services 中创建自定义服务文件 使用 Ant 可以这样做 https ant apache org manual Tasks jar html https ant apache or
  • 在实时数据库上运行 mysqldump

    只是想知道在实时数据库上运行 mysqldump 有哪些风险 是否存在数据库损坏的可能性 mysqldump 似乎锁定了整个数据库 您的数据库表使用什么引擎 如果您使用事务表 您可以使用选项 单事务 转储 这将以一致的状态转储您的表 如果您
  • Python:Scrapy CSV 导出不正确?

    我只是想写入 csv 但是 我有两个单独的 for 语句 因此每个 for 语句的数据独立导出并破坏顺序 建议 def parse self response hxs HtmlXPathSelector response titles hx
  • 在 docker 容器中安装 imagemagick

    我正在尝试在 Ubuntu 14 04 服务器上使用 ImageMagick 在上传到 s3 之前调整图像大小 我正在 Wercker 创建的 docker 容器内运行所有内容 问题是我已经将它安装在服务器上 并将其安装在 docker 容
  • NoSuchBeanDefinitionException:未找到与 spring 测试和 Junit 相关的合格 bean 类型

    我正在使用 spring 测试和 Junit 编写测试用例 并在初始化 bean 时遇到错误 我发现了很多关于此的帖子 但对我来说没有任何作用 下面是我的代码 Pom xml
  • 如何使用 css 模块调整网站上的水豚查找器?

    在我们的自动化测试中 代码中的典型行可能类似于 find edit icon click 我们正在我们的项目中使用 css modules 我被警告说类名可能会发生巨大的变化 一个非常滑稽的例子是这个网站在其类名称中使用表情符号 当您检查页
  • POST json 到 Rails 服务器

    def create req ActiveSupport JSON decode request body if user User authenticate req email req password session user id u
  • 使用“抛出”脚本来阻止 Safari 加载脚本 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 您好 我需要阻止 Safari 桌面加载脚本 Throw 可能是一个选项 但不确定如何针对特定浏览器 这会正确定位浏览器吗 if ch
  • android中遍历复杂的xml文件

    我有一个 xml 文件位于此链接上 http nchc dl sourceforge net project Trialxml options xml http nchc dl sourceforge net project trialxm
  • 如何从 Visual Studio 调试器执行所有进程内存的高级搜索?

    我是一个大型商业程序的开发人员 我正在尝试追踪特定的 C 内存泄漏 我想使用 Visual Studio 搜索进程的整个有效地址空间 但我不知道如何有效地执行此搜索 我知道 s 命令文档here http msdn microsoft co
  • 多个派生类的dynamic_cast

    我有一个基类和n派生类 我想实例化一个派生类并将其发送到一个接收基类作为参数的函数 在函数内部 我通过使用dynamic cast找到了它是哪种类型的派生类 但我不想使用几个if else语句 相反 我想知道是否有一种方法可以找出它是哪个派