Trouver le type d'un objet en C++

J'ai une classe A et une autre classe qui en hérite, B. je remplace une fonction qui accepte un objet de type A comme paramètre, donc je dois accepter un A. Cependant, j'appelle plus tard des fonctions que seul B a, donc je veux retourner false et ne pas continuer si l'objet passé n'est pas de type B.

Quel est le meilleur moyen de savoir quel type est l'objet passé à ma fonction?

123
demandé sur lemnisca 2008-12-09 08:06:51

11 réponses

Dynamic_cast devrait faire l'affaire

TYPE& dynamic_cast<TYPE&> (object);
TYPE* dynamic_cast<TYPE*> (object);

Le dynamic_cast keyword convertit une donnée d'un pointeur ou d'un type de référence à un autre, en effectuant une vérification d'exécution pour assurer la validité de la conversion.

Si vous essayez de lancer un pointeur vers un type qui n'est pas un type d'objet réel, le résultat de la distribution sera NULL. Si vous tentez de lancer une référence à un type qui n'est pas un type d'objet réel, la distribution lancera un bad_cast exception.

Marque bien sûr, il y a au moins une fonction virtuelle dans la classe de Base pour faire fonctionner dynamic_cast.

137
répondu yesraaj 2013-06-07 15:13:12

La distribution dynamique est la meilleure pour votre Description du problème, mais je veux juste ajouter que vous pouvez trouver le type de classe avec:

#include <typeinfo>

...
string s = typeid(YourClass).name()
121
répondu Robocide 2017-02-17 15:21:56

Cela s'appelle RTTI, mais vous voulez presque sûrement reconsidérer votre conception ici, car trouver le type et faire des choses spéciales en fonction de cela rend votre code plus fragile.

21
répondu Paul Betts 2008-12-09 05:09:06

Probablement intégrer dans vos objets un ID " tag " et l'utiliser pour distinguer entre les objets de classe A et les objets de classe B.

Cela montre cependant une faille dans la conception. Idéalement, ces méthodes dans B Que A n'a pas, devraient faire partie de A mais laisser vide, et B les écrase. Cela supprime le code spécifique à la classe et est plus dans l'esprit de la POO.

8
répondu freespace 2008-12-09 05:13:20

Cherchez-vous dynamic_cast<B*>(pointer)?

6
répondu Joshua 2014-02-22 19:49:07

Juste pour être complet, je vais construire build off de Robocide et souligner que typeid peut être utilisé seul sans utiliser name ():

#include <typeinfo>
#include <iostream>

using namespace std;

class A {
public:
    virtual ~A() = default; // We're not polymorphic unless we
                            // have a virtual function.
};
class B : public A { } ;
class C : public A { } ;

int
main(int argc, char* argv[])
{
    B b;
    A& a = b;

    cout << "a is B: " << boolalpha << (typeid(a) == typeid(B)) << endl;
    cout << "a is C: " << boolalpha << (typeid(a) == typeid(C)) << endl;
    cout << "b is B: " << boolalpha << (typeid(b) == typeid(B)) << endl;
    cout << "b is A: " << boolalpha << (typeid(b) == typeid(A)) << endl;
    cout << "b is C: " << boolalpha << (typeid(b) == typeid(C)) << endl;
}

Sortie:

a is B: true
a is C: false
b is B: true
b is A: false
b is C: false
4
répondu firebush 2016-03-31 18:53:28

Comme d'autres l'ont indiqué, vous pouvez utiliser dynamic_cast. Mais généralement, l'utilisation de dynamic_cast pour trouver le type de la classe dérivée sur laquelle vous travaillez indique la mauvaise conception. Si vous remplacez une fonction qui prend le pointeur de A comme paramètre, elle devrait pouvoir fonctionner avec les méthodes/données de la classe A elle-même et ne devrait pas dépendre des données de la classe B. dans votre cas, au lieu de surcharger si vous êtes sûr que la méthode que vous écrivez fonctionnera uniquement avec la Classe B, alors vous devrait écrire une nouvelle méthode dans la classe B.

2
répondu Naveen 2008-12-09 06:51:02

Parce que votre classe n'est pas polymorphe. Essayez:

struct BaseClas { int base; virtual ~BaseClas(){} };
class Derived1 : public BaseClas { int derived1; };

Maintenant BaseClas est polymorphe. J'ai changé la classe en struct car les membres d'une structure sont publics par défaut.

2
répondu c64zottel 2011-09-12 18:18:04

Votre description est un peu déroutante.

D'une manière générale, bien que certaines implémentations c++ aient des mécanismes pour cela, vous n'êtes pas censé poser des questions sur le type. Au lieu de cela, vous êtes censé faire un dynamic_cast sur le pointeur vers A. Ce que cela fera est qu'à l'exécution, le contenu réel du pointeur vers A sera vérifié. Si vous avez un B, vous obtiendrez votre pointeur vers B. Sinon, vous obtiendrez une exception ou null.

1
répondu Uri 2008-12-09 05:10:22

Utilise des fonctions surchargées. Ne nécessite pas de support dynamic_cast ou même RTTI:

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

class Foo {
public:
    void Bar(A& a) {
        // do something
    }
    void Bar(B& b) {
        Bar(static_cast<A&>(b));
        // do B specific stuff
    }
};
0
répondu jmucchiello 2008-12-09 07:05:18

Si vous pouvez accéder à la bibliothèque boost, peut-être type_id_with_cvr() fonction est ce que vous avez besoin, qui peut fournir Type de données sans enlever modificateurs const, volatile, & et & & . Voici un exemple simple en C++11:

#include <iostream>
#include <boost/type_index.hpp>

int a;
int& ff() 
{
    return a;
}

int main() {
    ff() = 10;
    using boost::typeindex::type_id_with_cvr;
    std::cout << type_id_with_cvr<int&>().pretty_name() << std::endl;
    std::cout << type_id_with_cvr<decltype(ff())>().pretty_name() << std::endl;
    std::cout << typeid(ff()).name() << std::endl;
}

Espère que cela est utile.

0
répondu Kehe CAI 2017-12-04 09:07:33