如何检查对象的类型是否是 C 中的特定子类?

新手上路,请多包涵

我正在考虑使用 typeid() 但我不知道如何询问该类型是否是另一个类的子类(顺便说一下,它是抽象的)

原文由 Chad 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

你真的不应该。如果您的程序需要知道对象是什么类,那通常表明存在设计缺陷。看看你是否可以使用虚函数获得你想要的行为。此外,有关您正在尝试做的事情的更多信息会有所帮助。

我假设你有这样的情况:

 class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

如果这是您所拥有的,请尝试执行以下操作:

 class Base
{
  virtual void bar() = 0;
};

class A : public Base
{
  void bar() {/* do X */}
};

class B : public Base
{
  void bar() {/* do Y */}
};

void foo(Base *p)
{
  p->bar();
}

编辑: 由于关于这个答案的争论在这么多年后仍在继续,我想我应该提供一些参考资料。如果你有一个基类的指针或引用,并且你的代码需要知道对象的派生类,那么它就违反了 Liskov 替换原则Bob 大叔 将此称为“ 对面向对象设计的诅咒”。

原文由 Dima 发布,翻译遵循 CC BY-SA 3.0 许可协议

我在这里看到了一些很好的答案,我看到了一些愚蠢的回应。

“试图查询对象的类型是一个设计缺陷”。这意味着Java instanceof 和C# 是关键字是设计缺陷。这些是不评价多态性的人的反应。如果您有一个接口,则该接口是由另一个实现更多功能的接口派生的。如果您需要这些额外的功能,您必须首先检查您是否有这样的接口。甚至微软的 COM API 也使用了这种设计。

那么在如何推断一个对象是否是一个类的实例方面,已经给出了很多很好的答案

  • 类型标识
  • 具有虚类型函数
  • 动态演员表

is_base_of 与多态无关。

并且让每个虚函数定义自己的类型方法是不必要的,因为它是多余的。每个虚拟类已经有一个指向它的虚拟表的指针。

 class Base
{
 void *p_virtual_table = BASE_VIRTUAL_TABLE;
}

class Derived : Base
{
 void *p_virtual_table = DERIVED_VIRTUAL_TABLE;
}

void *BASE_VIRTUAL_TABLE[n];
void *DERIVED_VIRTUAL_TABLE[n];

这里的重点是虚拟表的地址是固定的,一个简单的比较将决定一个虚拟对象是否是一个虚拟类的实例。

由于 cpp 没有为我们提供访问虚拟表的标准方法,因此很难手动进行这些比较。但是 cpp 抽象机在推断虚拟对象的确切实例时绝对没有问题。

原文由 user13947194 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题