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