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

我正在考虑使用typeid()但是我不知道如何判断这个types是否是另一个类的子类(顺便说一句,这是抽象的)

你真的不应该。 如果你的程序需要知道一个对象是什么类,那通常表明一个devise缺陷。 看看你是否可以使用虚拟function得到你想要的行为。 此外,有关您正在尝试做什么的更多信息将有所帮助。

我假设你有这样的情况:

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

编辑:由于关于这个答案的辩论在这么多年以后仍然继续,我想我应该引用一些参考。 如果你有一个基类的指针或引用,并且你的代码需要知道该对象的派生类,那么它违反了Liskovreplace原则 。 Bob叔叔把这称为“ 面向对象devise的诅咒 ”。

 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 (至less对于多态types)来完成。

其实,第二个想法 – 你不能确定它是否是一个特定的dynamic_casttypes – 但你可以告诉它是否是该types或其任何子类。

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

dynamic_cast可以确定types是否包含inheritance层次结构中任何位置的目标types(是的,这是一个鲜为人知的特性,如果Binheritance自AC ,它可以将A*直接转换为C* )。 typeid()可以确定对象的确切types。 但是,这些都应该非常谨慎地使用。 正如已经提到的,你应该总是避免dynamictypes识别,因为它表明了一个devise缺陷。 (另外,如果你知道对象是确定的目标types的话,你可以用static_cast做一个downcast,Boost提供了一个polymorphic_downcast ,它将在debugging模式下执行dynamic_cast的downcast,在release模式下它将会使用一个static_cast )。

我不同意你不应该在C ++中检查对象的types。 如果你能避免它,我同意你应该。 说你永远不应该在任何情况下这样做太过分了。 你可以用很多种语言来做到这一点,它可以让你的生活变得更轻松。 例如,Howard Pinsley向我们展示了他在C#中的职位。

我在Qt框架上做了很多工作。 一般来说,我以他们的方式做事(至less在他们的框架中工作的时候)的模式。 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 ,确定D是否是B的子类(反之亦然?)

解决scheme:使用一些模板魔法! 好的,你要看看LOKI这个由传奇C ++作者Andrei Alexandrescu制作的优秀的模板元编程库。

更具体地说,下载LOKI并在源代码中包含TypeManip.hTypeManip.h ,然后使用SuperSubclass类模板,如下所示:

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

根据文档,如果BD的公共基础,或者BD是相同types的别名,则SuperSubClass<B,D>::value将为真。

DB一个子类或DB相同。

我希望这有帮助。

编辑:

请注意SuperSubClass<B,D>::value发生在编译时,与使用dynamic_cast某些方法不同,因此在运行时使用此系统没有任何损失。

在C#中,你可以简单地说:

 if (myObj is Car) { } 
 #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函数,它会产生一个指向包含types信息的type_info结构的指针。

在维基百科上阅读

我正在考虑使用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 } } 
Interesting Posts