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 en tant que paramètre. Je dois donc accepter un A. Cependant, j'appellerai plus tard des fonctions que seul B a donc je veux retourner false et ne pas continuer si l'objet transmis n'est pas de type B.
Quel est le meilleur moyen de savoir quel type d'objet est transmis à ma fonction?
dynamic_cast devrait faire l'affaire
TYPE& dynamic_cast<TYPE&> (object);
TYPE* dynamic_cast<TYPE*> (object);
Le mot clé dynamic_cast
transfère une donnée d'un pointeur ou d'un type de référence à un autre, en effectuant une vérification à l'exécution pour s'assurer de la validité de la conversion.
Si vous essayez de transtyper un pointeur sur un type qui n'est pas un type d'objet réel, le résultat de la transposition sera NULL. Si vous essayez de faire référence à un type qui n'est pas un type d'objet réel, la conversion lève une exception bad_cast
.
Assurez-vous qu'il y a au moins une fonction virtuelle dans la classe de base pour que dynamic_cast fonctionne.
La conversion dynamique convient le mieux à votre description du problème, .__, mais je tiens simplement à ajouter que vous pouvez trouver le type de classe avec:
#include <typeinfo>
...
string s = typeid(YourClass).name()
Ceci s'appelle RTTI , mais vous voudrez sûrement reconsidérer votre conception ici, car le fait de rechercher le type et de faire des opérations spéciales en conséquence rend votre code plus fragile.
Intégrez probablement dans vos objets un "tag" ID et utilisez-le pour distinguer les objets de classe A des objets de classe B.
Cela montre cependant une faille dans la conception. Idéalement, les méthodes de B que A n’a pas doivent faire partie de A mais doivent rester vides et B les écrase. Cela supprime le code spécifique à la classe et correspond davantage à l'esprit de la programmation orientée objet.
Recherchez-vous dynamic_cast<B*>(pointer)
?
Pour être complet, je vais construire à partir 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
Parce que votre classe n'est pas polymorphe. Essayer:
struct BaseClas { int base; virtual ~BaseClas(){} };
class Derived1 : public BaseClas { int derived1; };
Maintenant, BaseClas
est polymorphe. J'ai changé de classe en struct car les membres d'une structure sont publics par défaut.
Comme d'autres l'ont indiqué, vous pouvez utiliser dynamic_cast. Mais en règle générale, utiliser dynamic_cast pour déterminer le type de la classe dérivée sur laquelle vous travaillez indique la mauvaise conception. Si vous substituez une fonction qui prend le pointeur de A comme paramètre, vous devriez pouvoir utiliser les méthodes/données de la classe A elle-même et ne pas dépendre des données de la classe B. êtes sûr que la méthode que vous écrivez ne fonctionnera qu'avec la classe B, vous devriez alors écrire une nouvelle méthode dans la classe B.
Votre description est un peu déroutant.
De manière générale, bien que certaines implémentations C++ disposent de mécanismes, vous n'êtes pas censé poser de questions sur le type. Au lieu de cela, vous êtes censé faire un dynamic_cast sur le pointeur sur A. Cela permettra de vérifier que, lors de l'exécution, le contenu du pointeur sur A sera vérifié. Si vous avez un B, vous obtiendrez votre pointeur sur B. Sinon, vous obtiendrez une exception ou une valeur nulle.
Utilisez des fonctions surchargées. Ne nécessite pas le 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, vous pouvez éventuellement utiliser la fonction type_id_with_cvr (), qui peut fournir le type de données sans supprimer 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;
}
J'espère que c'est utile.