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

有帮助吗?

解决方案

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

我假设你有这样的情况:

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();
}

编辑:由于关于这个答案的辩论在这么多年后仍然存在,我想我应该引用一些参考资料。如果你有一个指针或对基类的引用,并且你的代码需要知道对象的派生类,那么它违反了利斯科夫替代原则鲍勃叔叔将此称为<!>“; 面向对象设计的诅咒 <!>”。

其他提示

NBSP <!>;

class Base
{
  public: virtual ~Base() {}
};

class D1: public Base {};

class D2: public Base {};

int main(int argc,char* argv[]);
{
  D1   d1;
  D2   d2;

  Base*  x = (argc > 2)?&d1:&d2;

  if (dynamic_cast<D2*>(x) == nullptr)
  {
    std::cout << "NOT A D2" << std::endl;
  }
  if (dynamic_cast<D1*>(x) == nullptr)
  {
    std::cout << "NOT A D1" << std::endl;
  }
}

你可以用dynamic_cast(至少对于多态类型)来做。

实际上,在第二个想法 - 你无法判断它是否特别是<=>的特定类型 - 但你可以判断它是否是那种类型或其任何子类。

template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
  return dynamic_cast<const DstType*>(src) != nullptr;
}

dynamic_cast可以确定类型是否在继承层次结构中的任何位置包含目标类型(是的,如果B继承自AC,它可以转为<=一个鲜为人知的特性) >直接进入A*)。 C*可以确定对象的确切类型。但是,这两者都应该非常谨慎地使用。如前所述,您应始终避免动态类型识别,因为它表明存在设计缺陷。 (另外,如果您知道对象是确定目标类型,则可以使用typeid()进行向下转换.Boost提供static_cast将在调试模式下使用polymorphic_downcastassert进行向下转换,在发布模式下,它只使用<=>)。

我不同意你永远不想在C ++中检查一个对象的类型。如果你可以避免它,我同意你应该。说你永远不应该在任何情况下做到这一点太过分了。你可以用很多种语言来做这件事,它可以让你的生活更轻松。例如,霍华德·平斯利(Howard Pinsley)向我们展示了他在C#上的帖子。

我在Qt Framework上做了很多工作。一般来说,我会按照他们做事的方式(至少在他们的框架中工作时)对我的行为进行建模。 QObject类是所有Qt对象的基类。该类具有函数isWidgetType()和isWindowType()作为快速子类检查。那么为什么不能检查你自己的派生类,它的性质是否可比?以下是其他一些帖子的QObject分拆:

class MyQObject : public QObject
{
public:
    MyQObject( QObject *parent = 0 ) : QObject( parent ){}
    ~MyQObject(){}

    static bool isThisType( const QObject *qObj )
    { return ( dynamic_cast<const MyQObject*>(qObj) != NULL ); }
};

然后当你传递一个指向QObject的指针时,你可以通过调用静态成员函数来检查它是否指向你的派生类:

if( MyQObject::isThisType( qObjPtr ) ) qDebug() << "This is a MyQObject!";

我不知道我是否理解你的问题,所以让我用自己的话来重述......

问题:给定类BD,确定TypeManip.hSuperSubclass的子类(反之亦然?)

解决方案:使用一些模板魔法!好的,你需要看看LOKI,这是一个出色的模板元编程库,由传说中的C ++作者Andrei Alexandrescu制作。

更具体地说,下载 LOKI 并包含标题< =>在源代码中使用SuperSubClass<B,D>::value类模板,如下所示:

if(SuperSubClass<B,D>::value)
{
...
}

根据文档,如果dynamic_cast是<=>的公共基础,或者<=>和<=>是同一类型的别名,<=>将是真实的。

即。 <=>是<=>的子类或<=>与<=>相同。

我希望这会有所帮助。

修改

请注意<=>的评估在编译时发生,与使用<=>的某些方法不同,因此在运行时使用此系统不会受到任何惩罚。

#include <stdio.h>
#include <iostream.h>

class Base
{
  public: virtual ~Base() {}

  template<typename T>
  bool isA() {
    return (dynamic_cast<T*>(this) != NULL);
  }
};

class D1: public Base {};
class D2: public Base {};
class D22: public D2 {};

int main(int argc,char* argv[]);
{
  D1*   d1  = new D1();
  D2*   d2  = new D2();
  D22*  d22 = new D22();

  Base*  x = d22;

  if( x->isA<D22>() )
  {
    std::cout << "IS A D22" << std::endl;
  }
  if( x->isA<D2>() )
  {
    std::cout << "IS A D2" << std::endl;
  }
  if( x->isA<D1>() )
  {
    std::cout << "IS A D1" << std::endl;
  }
  if(x->isA<Base>() )
  {
    std::cout << "IS A Base" << std::endl;
  }
}

结果:

IS A D22
IS A D2
IS A Base

除非使用RTTI,否则只能在编译时使用模板执行此操作。

它允许你使用typeid函数,它将产生一个指向type_info结构的指针,该结构包含有关该类型的信息。

维基百科上阅读

在c#中你可以简单地说:

if (myObj is Car) {

}
  

我正在考虑使用typeid() ...

嗯,是的,可以通过比较来完成:typeid().name()。如果我们采取已经描述的情况,其中:

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

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

foo(Base *p)的可能实现方式是:

#include <typeinfo>

void foo(Base *p)
{
    if(typeid(*p) == typeid(A))
    {
        // the pointer is pointing to the derived class A
    }  
    else if (typeid(*p).name() == typeid(B).name()) 
    {
        // the pointer is pointing to the derived class B
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top