Vérifiez si la classe est dérivée d'une classe spécifique (compilation, exécution à la fois des réponses disponibles)
Il est plus facile d'expliquer sur un exemple donc,
class base {
//....
}
class derived1 : public base {
//...
}
Dans ma bibliothèque, il est un pointeur de classe de base. L'utilisateur de la bibliothèque ont à rendre les classes dérivées à partir de la base ou derived1 et attribuer pointeur vers la classe.
Comment puis-je vérifier ce que la classe est définie par l'utilisateur de la classe dérivée?
Moment de l'exécution ou de la compilation?
Moment de la compilation ....
Pour la compilation, vous pouvez regarder ici pour le trait qui permet de vérifier si X est une base de v
Êtes-vous à l'aide de C++11? Si donc utiliser les
Pour la compilation, vous avez
Moment de la compilation ....
Pour la compilation, vous pouvez regarder ici pour le trait qui permet de vérifier si X est une base de v
Êtes-vous à l'aide de C++11? Si donc utiliser les
std::is_base_of
.Pour la compilation, vous avez
std::is_base_of
.
OriginalL'auteur khajvah | 2013-08-07
Vous devez vous connecter pour publier un commentaire.
J'ai quelques remarques sur le projet au moment de la compilation x les solutions d'exécution. En plus lorsqu'ils sont évalués,
is_base_of
etdynamic_cast
ont des exigences différentes et leurs réponses peuvent être différentes.(1) tout d'Abord (comme souligné par d'autres) à utiliser
dynamic_cast
, de base et les classes dérivées doivent être polymorphe (il doit y avoir au moins unvirtual
méthode).is_base_of
ne nécessite pas les types polymorphes.(2) Les opérandes de
is_base_of
sont les deux types alors quedynamic_cast
a besoin d'un type (à l'intérieur de< >
) et un objet (à l'intérieur de( )
).(3)
dynamic_cast
etis_base_of
peuvent donner des réponses différentes (ou on peut le compiler, tandis que l'autre ne fonctionne pas) selon le type d'héritage (public
vsprotected
ouprivate
). Par exemple envisager:Nous avons
En fait, la dernière ligne donne une erreur de compilation de GCC (
error: 'B' is an inaccessible base of 'D2'
). VS2010 ne le compiler (rendement juste un avertissement similaire à GCC de message d'erreur).(4) les exigences sur Les classes polymorphes peuvent être assouplies par le biais d'un traitement d'exception truc. Considérer:
Puis nous avons
Il est digne que
is_unambiguous_public_base_of
est beaucoup plus lent quedynamic_cast
et (c'est devenu plus évident après le changement de nom mentionné dans la mise à jour ci-dessous) renvoie toujours unnullptr
pour downcasts:Un peu désuète de référence sur cette astuce est ici.
Avertissement: la mise en œuvre de
is_unambiguous_public_base_of
ci-dessus n'est qu'un projet pour faire le point, et il ne gère pasconst
etvolatile
qualifications correctement.Mise à jour: Dans une version précédente de ce post
is_unambiguous_public_base_of
a été nommémy_dynamic_cast
et cela a été une source de confusion. Donc, je l'ai renommé pour un nom plus significatif. (Merci à Jan Herrmann.)B*
qui pointe vers unD1
à unD1*
.Herrmann: Quel est exactement le problème? Oui, à l'aide de
my_dynamic_cast
sortsD1*
àB*
rendements non NULL ptr (comme je l'ai dit,assert((my_dynamic_cast<B>(&d1)));
passe). À l'aide deD2*
àB*
rendements NULL ptr (comme je l'ai dit,assert(!(my_dynamic_cast<B>(&d2)));
passe). De l'utiliser pour downcasts (contrarilly àdynamic_cast
) renvoie TOUJOURS NULL ptr (comme je l'ai dit,assert(!(my_dynamic_cast<D1>(b1)));
passe). Je n'ai jamais dit queis_base_of
,dynamic_cast
etmy_dynamic_cast
peut remplacer l'un de l'autre. C'est le but de mon post: pour montrer leurs différences dans la sémantique et les exigences.regardez coliru.stacked-crooked.com/... j'ai ajouté les lignes 28 et 29, c'est ce que j'attends d'un remplacement de
dynamic_cast
. Si votre partie 4 est inutile. Il fait quelque chose qui peut être réalisé avec une simple surcharge de fonctions (ce qui aurait pour résultat le même questatic_cast
). Alors, quel est son but?Encore une fois, je n'ai jamais dit que
my_dynamic_cast
est un remplacement pourdynamic_cast
(je suis d'accord que j'aurais pu choisir un meilleur nom). En plus de votre testassert(my_dynamic_cast<D1>(b1));
est exactement à l'opposé de la mienne:assert(!(my_dynamic_cast<D1>(b1))); // Notice the negation.
(Voir ci-dessus).La confusion est due principalement pour le nom que j'ai choisi:
my_dynamic_cast
. Donc, je vais mettre à jour le post pour le renommer, par exemple,my_is_base_of
;-). Merci pour la discussion de toute façon.OriginalL'auteur Cassio Neri
Vous pouvez utiliser dynamic_cast.
dynamic_cast
effectueruntime
vérifier et de conversion.Oui, c'est exactement cela.
Mais il veut vérifier au compilateur de temps. Il devrait peut-être changer le titre de la question.
OriginalL'auteur sashoalm
Vous pouvez utiliser
std::is_base_of
:isBase
est vrai siTheOtherClass
est dérivé debase
.OriginalL'auteur juanchopanza
Je pense que la réponse à cette question est très difficile. Bien sûr, il est
std::is_base_of
etdynamic_cast
. Les deux vous fournir des informations très limitées. La troisième option est de surcharge de fonctions. Avec toutes ces techniques, vous pouvez choisir un chemin spécial dans votre code qui doit être exécuté.std::is_base_of
peut être interprétée dans un contexte booléen, et c'est un dérivé de lastd::true_type
oustd::false_type
. Ce fait rend-il possible de l'utiliser comme paramètre d'une fonction et l'utilisation du temps de compilation polymorphisme via la fonction de surcharge. Ce premier exemple montre comment l'utiliser dans un contexte booléen, mais vous n'avez pas tout autre type spécifique de l'information. Si la compilation échoue dans la plupart des cas (voir ici pour une description plus détaillée):La deuxième version est simple surcharge de fonctions. Ici, le temps de compilation polymorphisme est utilisé, mais tous les runtime type d'information est perdue (à l'exception des fonctions virtuelles et
dynamic_cast
sont utilisés):Maintenant la troisième version combine à la fois:
La troisième variante est normalement utilisé pour l'en-tête uniquement les bibliothèques qui n'utilisent pas le moteur d'exécution poylmorphism (recherche de
std::advance
pour un excample).Maintenant polymorphisme d'exécution. Ici vous avez la
dynaminc_cast
variante:Si cette variante n'est pas assez rapide, vous pouvez mettre en œuvre votre onw fonte à derived1:
C'est rapide, mais elle s'adapte très bien pour seulement très peu de (environ 1) les classes dérivées.
Le dernier mais non le moins, vous devriez penser au sujet de votre conception de classe et deside quelles sont les méthodes pour faire de virtuel et de mettre en œuvre dans
base
,derived1
ou d'autres classes. Vous devriez certainement regarder pour modèle de stratégie.std::true/false_type::value
pas le type lui-même.merci, je l'ai changé (Une valeur construite devraient aussi).
OriginalL'auteur Jan Herrmann
Vous pouvez le faire de plusieurs façons. Les plus courantes comme les autres l'ont souligné, sont dynamic_cast<> et std::is_base_of. Ce dernier est utilisé au moment de la compilation, tandis que
dynamic_cast<>
peut être utilisé lors de l'exécution.CEPENDANT,
dynamic_cast<>
ne fonctionnera que si votre classe est polymorphe (c'est à dire avoir au moins une fonction virtuelle - il peut être une méthode ou le destructeur). Si pas, le compilateur va déclencher une erreur.OriginalL'auteur Iosif Murariu
Le compilateur acceptera uniquement les pointeurs vers les classes dérivées à partir de votre classe de base si vos fonctions de la bibliothèque prend des pointeurs de la classe de base. Ma réponse est avec une approche classique de type de sécurité de la poignée. De mon expérience, ce genre de type de vérification est assez. Ayant 25 ans d'expérience dans l'industrie, j'ai question de la nécessité de faire cette vérification. Peut-être une telle question fondamentale n'est pas la bienvenue? Je voudrais voir la justification d'avoir le besoin de faire ce genre de sortie. Je n'ai jamais eu à le faire. À l'opposé, c'est à dire une baisse de cast j'ai besoin assez fréquemment.
OriginalL'auteur Frodo