IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

RTTI


Sujet :

C++

  1. #1
    Candidat au Club
    Inscrit en
    Décembre 2004
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 3
    Points : 4
    Points
    4
    Par défaut RTTI
    Bonjour,

    Je voudrais savoir si les RTTI impactent les performances de code C++, avec le compilateur de Visual C++ 6.0.
    Si oui, dans quelles mesures les performances sont-elles impactées ?
    Merci !

    Jean-Marc

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Certain que ça impacte les performances ! C'est du code en plus, de la vérification à l'exécution à la place de la compilation !

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 109
    Points : 121
    Points
    121
    Par défaut
    D'après ce que j'en sais et en m'appuyant sur le livre "Pour mieux développer avec C++" (cf ressources du site), voici ce qu'ils en disent des RTTI :

    - Pas de typeid (le truc tout pourri indiquant la classe d'un objet)
    - Pas de const_cast (plutôt le mot clé mutable) ni reinterpret_cast (à banir).
    - Utiliser static_cast plutôt que l'opérateur de conversion du C.
    - Utiliser les fonctions virtuelles (polymorphiques) quand c'est possible, se rabattre sur le dynamic_cast (en gros, c'est comme static_cast sauf que ça gère l'héritage et surtout il y a une vérification avant de convertir).

    Niveau performances :
    - Une fonction virtuelle peut demander 30% de temps en plus par appel (et non à l'éxécution). Il vaut mieux éviter les enchaînements d'appel.
    - Dynamic_cast peut la plupart du temps être évité si l'ULM associée est bien faite. Dynamic_cast est beaucoup plus long que static_cast à cause de la vérification. Je n'ai pas de chiffres précis, juste le beaucoup.


    En gros, RTTI = quand t'as pas le choix, mais le livre souligne combien l'ulm est importante, bon diagramme de classes -> presque pas de RTTI.

    Voilà.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 109
    Points : 121
    Points
    121
    Par défaut
    euh comprendre UML plutôt que ULM

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Kaktus
    D'après ce que j'en sais et en m'appuyant sur le livre "Pour mieux développer avec C++" (cf ressources du site), voici ce qu'ils en disent des RTTI :

    - Pas de typeid (le truc tout pourri indiquant la classe d'un objet)
    Sauf que ce typeid utilise uniquement de la mémoire en plus par classe (et non par objet) ayant une fonction virtuelle. En général, totalement négligeable.
    Citation Envoyé par Kaktus
    - Une fonction virtuelle peut demander 30% de temps en plus par appel (et non à l'éxécution). Il vaut mieux éviter les enchaînements d'appel.
    Sauf qu'en général une fonction virtuelle en C++ est destinée à remplacer non pas une fonction non virtuelle, mais le couple (fonction non virtuelle + switch). Comparer le coût d'appel pur n'a pas trop de sens. Et dans certains cas, le compilateur peut faire les appels avec 0% de perte. Donc cette valeur de 30%, si elle n'est pas détaillée, me semble douteuse.
    Citation Envoyé par Kaktus
    - Dynamic_cast peut la plupart du temps être évité si l'ULM associée est bien faite. Dynamic_cast est beaucoup plus long que static_cast à cause de la vérification. Je n'ai pas de chiffres précis, juste le beaucoup.
    Mais il est beaucoup plus sur. Si l'on fait du downcast (cast vers le bas de la hiérarchie), il vaut mieux utiliser du dynamic_cast, qui est là pour ça, plutôt qu'un certain nombre de bidouilles marchant à moitié que j'ai vu ça et là (genre l'utilisateur défini une fonction type dans sa hiérarchie, et fait des vérifications manuelles qui ne marchent pas (exercice au lecteur : Quel est l'erreur souvent commise ?)).

    Ce qui est souvent (mais pas toujours) évitable, c'est le downcast. Si on doit faire du downcast, dynamic_cast est une bonne solution pour y parvenir.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 109
    Points : 121
    Points
    121
    Par défaut
    Les critiques du typeid sont pour le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if ( typeid(*animalpt) == typeid(Chien)) animalpt->aboyer();
    if ( typeid(*animalpt) == typeid(Chat))  animalpt->miauler();
     
    //etc...
    Ce type de code est mauvais dans le sens C++, mais plus rapide que de faire une classe virtuelle animal suivie d'une classe héritée Chien et une autre Chat avec une fonction virtuelle.


    Je ne défends pas du tout ce point de vue (je viens de Java ) et dans le fond je suis d'accord avec toi, mais la question posée n'est pas évidente je trouve et j'essaie d'être objectif... enfin j'essaie .

    Il y a une variable implicite, celle du temps. Concevoir un logiciel est synonyme de butoir temporel, alors il faut souvent fournir quelque chose qui marche à une date donnée, quite à l'améliorer après. Les RTTI servent à ça aussi, notamment les cast.


    Je ne comprends pas en quoi le dynamic_cast est plus sûr que static_cast. En fait, je vois plutôt ça comme deux opérateurs complémentaires, ( à moins que je me trompe ??) :
    - Type de l'objet connu à la compilation = static_cast.
    - Navigation sécurisée dans une hiérarchie de classes évolutive = dynamic_cast.
    - Identification par une fonction virtuelle si le modèle UML le spécifie (hiérarchie de classe fixée et non évolutive). J'entends par là une fonction virtuelle (de type booleen par exemple) qui permet d'identifier la classe de l'objet. Ceci gère aussi l'héritage et est beaucoup plus léger.
    - Si on n'a pas le choix : dynamic_cast.
    Un autre bémol rarement soulevé est qu'il faut des classes polymorphes pour utiliser dynamic_cast.


    D'ailleurs à ce propos, les auteurs conseillent carrément d'abord de tout en mettre d'en dynamic_cast (si manque de temps) puis d'analyser plus finement le programme et de remplacer progressivement par des static_cast à l'avenir.

    PS : Alors, l'histoire des 30%, ce sont des tests menés sur des compil Borland et visual C++ (pas les derniers). Il est précisé que ce malus est plutôt sensible quand il y a une multitude de petites fonctions virtuelles qui s'appellent. C'est qualifié d'anecdotique mais à savoir quand même.
    Voilà .


    Je me suis jamais servi de dynamic_cast, toujours static_cast ou la fonction virutelle car mes hiérarchies ont toujours été fixées et je n'utilise pas l'héritage multiple virtuel donc ...



    /mode emmerdeur on: Euh, ca me dirait bien un petit tuto en FAQ sur l'héritage multiple.
    /mode emmerdeur off.

    Bonne soirée.

  7. #7
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Je suis assez d'accord avec Kaktus...

    Au fait, le static_cast est équivalent au (type) ?

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Kaktus
    Je ne comprends pas en quoi le dynamic_cast est plus sûr que static_cast. En fait, je vois plutôt ça comme deux opérateurs complémentaires, ( à moins que je me trompe ??) :
    - Type de l'objet connu à la compilation = static_cast.
    Je dirais plutôt :
    upcast, cast numérique,... -> static_cast
    downcast -> dynamic_cast
    Si le type est connu à la compilation, on peut effectivement mettre un static_cast, puis à la première évolution du programme, boom. Mettre un dynamic_cast dans ce cas là me semble une assurance de sécurité, quitte à le remplacer par static_cast pendant la phase d'optimisation, mais pas avant. Voir par exemple http://www.boost.org/libs/conversion/cast.htm

    Citation Envoyé par Kaktus
    - Navigation sécurisée dans une hiérarchie de classes évolutive = dynamic_cast.
    Quel code n'est pas évolutif ?
    Citation Envoyé par Kaktus
    - Identification par une fonction virtuelle si le modèle UML le spécifie (hiérarchie de classe fixée et non évolutive). J'entends par là une fonction virtuelle (de type booleen par exemple) qui permet d'identifier la classe de l'objet. Ceci gère aussi l'héritage et est beaucoup plus léger.
    Ca fait partie de ce que j'appelle une mauvaise solution par peur de dynamic_cast. Je ne vois pas :
    - En quoi l'héritage est géré
    - En quoi c'est plus léger que dynamic_cast
    Citation Envoyé par Kaktus

    - Si on n'a pas le choix : dynamic_cast.
    Un autre bémol rarement soulevé est qu'il faut des classes polymorphes pour utiliser dynamic_cast.
    C'est en pratique rarement gênant, puisqu'il est rare de vouloir faire dynamic_cast en dehors d'une hiérarchie polymorphe, et qu'il est rare qu'une telle hiérarchie ne contienne pas déjà des fonctions virtuelles.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 109
    Points : 121
    Points
    121
    Par défaut
    Par hiérarchie non évolutive, j'entends un arbre hiérarchique fixe, par exemple, si tu veux faire un jeu d'échecs, tu as :
    - Une classe abstraite pion
    - des classes filles reine, roi, fou etc...

    Tu sais que ça n'évoluera jamais, qu'il n'y aura jamais de descendants, ni d'autres classes.

    Ou dans une boite tu as des salariés, des chefs et le patron, peu de chances que ça évolue ... Alors ton logiciel de fiches de paie.

    Cela étant absolument d'accord pour dire que si il y a évolution future crack boom d'où l'intérêt de vérouiller son UML avant si on peut .




    Pour la fonction virtuelle qui gère l'héritage, prenons cet exemple :
    - Une classe générique polygone.
    - Une classe fille triangle.
    - Une autre classe fille parallélogramme.

    classe triangle se décline en triangle quelconque puis triangle rectangle (admettons).
    classe parallélogramme se décline en classe rectangle, classe losange (admettons).

    Rien ne m'empêche de déclarer une fonction virtuelle isTriangle() dans la classe générique de la mettre fausse à tout forme non triangulaire.
    Un static_cast par dessus et voilà, plus rapide qu'un dynamic_cast, et s'il y a des classes filles d'un rectangle par exemple, eh bien c'est gérable sans difficultés.

    Plus finement, je peux aussi déclarer un hasAngleDroit() dans la classe générique, la mettre true au triangle rectangle et au rectangle et false au reste. Chose infaisable avec dynamic_cast par ailleurs, sauf si on revoit le modèle UML mais on tu risques de perdre la distinction triangle/ parallélogramme.


    C'est surtout pour ces raisons que je modère l'enthousiasme sur le dynamic_cast.
    D'un autre côté, je n'ai jamais participé à des projets très importants, alors ce que je pense à ce niveau ne s'applique qu'à des petits projets.
    Peut-être que je reverrai ma position si je suis amené à en faire.

    Peur du dynamic_cast, je ne pense pas , même si son mode de fonctionnement technique de est difficile à cerner pour moi, mais vu le nombre de fois que je lis que dynamic_cast se paye très cher niveau performances, je me dis que c'est à utiliser avec modération.

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Kaktus
    Rien ne m'empêche de déclarer une fonction virtuelle isTriangle() dans la classe générique de la mettre fausse à tout forme non triangulaire.
    Le problème est que dans ce cas, la classe de base doit avoir connaissance des ses classes filles, ce qui introduit une référence cyclique entre ces classes, ce qui est rarament une bonne idée. Par exemple, le jour où tu décides d'ajouter une classe pentagone, et que tu veux pouvoir downcaster, tu dois avoir accès à la classe de base en écriture (parmis les cas où le downcasting m'a servit, le plus courant est justement quand je ne peut pas modifier la classe de base pour y ajouter la fonction virtuelle qui va bien). Plus éventuellement modifier d'autres classes filles (comme polygone) pour ajouter cette fonction.

    Citation Envoyé par Kaktus
    Un static_cast par dessus et voilà, plus rapide qu'un dynamic_cast, et s'il y a des classes filles d'un rectangle par exemple, eh bien c'est gérable sans difficultés.
    As-tu fait le test de performances fonction virtuelle + static_cast comparé à dynamic_cast ?


    Citation Envoyé par Kaktus
    Plus finement, je peux aussi déclarer un hasAngleDroit() dans la classe générique, la mettre true au triangle rectangle et au rectangle et false au reste. Chose infaisable avec dynamic_cast par ailleurs, sauf si on revoit le modèle UML mais on tu risques de perdre la distinction triangle/ parallélogramme.
    Mais une telle fonction ne permet pas de faire du downcast... A moins d'une hiérarchie avec héritage multiple, dans laquelle dynamic_cast marche aussi.

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 109
    Points : 121
    Points
    121
    Par défaut
    JolyLoic : Absolument d'accord. Cependant, quand tu n'as pas accès aux classes de bases, c'est que tu ne les as pas écrites et que le créateur ne t'autorise pas à y entrer (biblio propriétaires etc...).
    Là oui, pas le choix ...
    Il est vrai qu'il y a aussi un côté dangereux à modifier la classe mère, effectivement, sauf si c'est ton projet et que tu as déjà prévu cette éventualité .
    Je pense vraiment que dynamic_cast c'est évitable en bonne partie, pour les petits projets comme moi.

    Niveau performances, oui je me suis amusé à faire une grosse boucle avec des dynamic_cast d'un côté et des fonctions virtuelles + static_cast, il n'y a pas photo. Même si dans 95% des prologiciels, on s'en fiche pas mal des performances.

    Oui aussi pour le hasAngleDroit(), avec héritage multiple non virtuel (ce qui facilite bcp les choses), suffit de faire une classe abstraite AngleDroit.

Discussions similaires

  1. Pointeur de Méthode et RTTI
    Par ShaiLeTroll dans le forum Delphi
    Réponses: 6
    Dernier message: 16/01/2007, 16h04
  2. Réponses: 1
    Dernier message: 26/11/2006, 16h42
  3. RTTI:Lister les propriétés d'une interface COM
    Par zeprogrameur dans le forum Langage
    Réponses: 10
    Dernier message: 09/11/2005, 16h06
  4. [RTTI] TObject.FieldAdress(Name : String) : Pointer
    Par Clorish dans le forum Langage
    Réponses: 3
    Dernier message: 30/09/2004, 14h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo