Comment vérifier si le type d’un object est une sous-classe particulière en C ++?

Je pensais à utiliser typeid() mais je ne sais pas comment demander si ce type est une sousclasse d’une autre classe (qui est d’ailleurs abstraite)

Tu ne devrais vraiment pas. Si votre programme doit connaître la classe d’un object, cela indique généralement un défaut de conception. Voyez si vous pouvez obtenir le comportement souhaité à l’aide des fonctions virtuelles. En outre, plus d’informations sur ce que vous essayez de faire aideraient.

Je suppose que vous avez une situation comme celle-ci:

 class Base; class A : public Base {...}; class B : public Base {...}; void foo(Base *p) { if(/* p is A */) /* do X */ else /* do Y */ } 

Si c’est ce que vous avez, alors essayez de faire quelque chose comme ceci:

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

Edit: Le débat sur cette réponse se poursuivant après tant d’années, j’ai pensé que je devrais lancer quelques références. Si vous avez un pointeur ou une référence à une classe de base et que votre code doit connaître la classe dérivée de l’object, il enfreint le principe de substitution de Liskov . Oncle Bob appelle cela un ” anathème à la conception orientée object “.

 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(x) == nullptr) { std::cout << "NOT A D2" << std::endl; } if (dynamic_cast(x) == nullptr) { std::cout << "NOT A D1" << std::endl; } } 

Vous pouvez le faire avec dynamic_cast (du moins pour les types polymorphes).

En fait, à la reflection – vous ne pouvez pas dire si c’est un type particulier avec dynamic_cast mais vous pouvez savoir si c’est ce type ou une de ses sous-classes.

 template  bool IsType(const SrcType* src) { return dynamic_cast(src) != nullptr; } 

dynamic_cast peut déterminer si le type contient le type cible n’importe où dans la hiérarchie d’inheritance (oui, c’est une caractéristique peu connue que si B hérite de A et C , il peut transformer un A* directement en C* ). typeid() peut déterminer le type exact de l’object. Cependant, ceux-ci doivent tous deux être utilisés avec parcimonie. Comme cela a déjà été mentionné, vous devez toujours éviter l’identification de type dynamic, car elle indique un défaut de conception. (De plus, si vous savez que l’object est sûr du type cible, vous pouvez effectuer un static_cast avec un static_cast . Boost propose un polymorphic_downcast qui fera un downcast avec dynamic_cast et assert en mode debug, et en mode release il utilisera simplement un static_cast ).

Je ne suis pas d’accord avec le fait que vous ne devriez jamais vouloir vérifier le type d’un object en C ++. Si vous pouvez l’éviter, je suis d’accord avec vous. Dire que vous ne devriez JAMAIS le faire en aucune circonstance va cependant trop loin. Vous pouvez le faire dans un grand nombre de langues et cela peut vous faciliter la vie. Howard Pinsley, par exemple, nous a montré comment dans son article sur C #.

Je travaille beaucoup avec le framework Qt. En général, je modélise ce que je fais après la façon dont ils font les choses (du moins lorsqu’ils travaillent dans leur cadre). La classe QObject est la classe de base de tous les objects Qt. Cette classe a les fonctions isWidgetType () et isWindowType () comme une vérification rapide de la sous-classe. Alors, pourquoi ne pas pouvoir vérifier vos propres classes dérivées, ce qui est comparable dans sa nature? Voici un extrait de QObject de certains de ces autres articles:

 class MyQObject : public QObject { public: MyQObject( QObject *parent = 0 ) : QObject( parent ){} ~MyQObject(){} static bool isThisType( const QObject *qObj ) { return ( dynamic_cast(qObj) != NULL ); } }; 

Et puis, lorsque vous passez un pointeur à un QObject, vous pouvez vérifier s’il pointe vers votre classe dérivée en appelant la fonction membre statique:

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

Je ne sais pas si je comprends votre problème correctement, alors laissez-moi le reformuler dans mes propres mots …

Problème: Étant donné les classes B et D , déterminez si D est une sous-classe de B (ou vice-versa?)

Solution: Utilisez un modèle magique! Ok, sérieusement, vous devez jeter un oeil à LOKI, une excellente bibliothèque de méta-programmation de modèles produite par l’auteur de C ++ légendaire Andrei Alexandrescu.

Plus précisément, téléchargez LOKI et incluez l’en-tête TypeManip.h dans votre code source, puis utilisez le SuperSubclass classe SuperSubclass comme suit:

 if(SuperSubClass::value) { ... } 

Selon la documentation, SuperSubClass::value sera vrai si B est une base publique de D , ou si B et D sont des alias du même type.

c’est-à-dire que D est une sous-classe de B ou D est la même chose que B

J’espère que ça aide.

modifier:

Veuillez noter que l’évaluation de SuperSubClass::value au moment de la compilation contrairement à certaines méthodes qui utilisent dynamic_cast , il n’y a donc aucune pénalité pour l’utilisation de ce système à l’exécution.

En c #, vous pouvez simplement dire:

 if (myObj is Car) { } 
 #include  #include  class Base { public: virtual ~Base() {} template bool isA() { return (dynamic_cast(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() ) { std::cout << "IS A D22" << std::endl; } if( x->isA() ) { std::cout << "IS A D2" << std::endl; } if( x->isA() ) { std::cout << "IS A D1" << std::endl; } if(x->isA() ) { std::cout << "IS A Base" << std::endl; } } 

Résultat:

 IS A D22 IS A D2 IS A Base 

Vous ne pouvez le faire qu’au moment de la compilation en utilisant des modèles, sauf si vous utilisez RTTI.

Il vous permet d’utiliser la fonction de typeid qui donnera un pointeur sur une structure de type_info contenant des informations sur le type.

Lisez-le sur Wikipedia

Je pensais à l’utilisation de typeid()

Eh bien, oui, cela pourrait être fait en comparant: typeid().name() . Si nous prenons la situation déjà décrite, où:

 class Base; class A : public Base {...}; class B : public Base {...}; void foo(Base *p) { if(/* p is A */) /* do X */ else /* do Y */ } 

Une implémentation possible de foo(Base *p) serait:

 #include  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 } }