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 :

Virtual or not virtual?


Sujet :

C++

  1. #1
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut Virtual or not virtual?
    Bonjour,

    Les mécanismes d'héritage et de polymorphismes sont liées en C++ à la définition de fonctions membres virtuelles. En Python, par exemple (car c'est par là que j'ai commencé) ou en Java, toutes les méthodes sont virtuelles et par conséquent la ligature est toujours dynamique (dynamic binding: le choix du type est effectué à l'exécution).

    J'utilise beaucoup l'héritage et le polymorphisme dans la structuration de mon code et, par conséquent, je déclare toutes mes méthodes de classe avec le qualificateur "virtual". En revanche, je ne comprend pas très bien dans quelles situations nous avons intérêt à forcer une ligature statique. Est-ce une question de performance, le choix du type à l'exécution étant une opération trop gourmande en resources? Vos commentaires sur les bonnes pratiques à adopter en la matière sont les bienvenus.

    Meilleures salutations

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  2. #2
    Membre habitué Avatar de BigNic
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 195
    Points : 154
    Points
    154
    Par défaut
    je ne sais pas si c'est propre ou non, mais moi cela m'arrive d'utiliser une ligature statique quand sur une classe qui est destiné à être dérivée je ve que des methodes ne puisse pas être redéfinies.
    Exemple j'ai une famille d'objet A (A1, A2, A3, ....) tous dérive de A. Dans A j'ai une fonction qui calcul un Id selon certaine données de bases. Et je veut avoir la main sur l'algorithme de calcul de l'Id. Par contrte chacune des classes à sa propre façon de traiter ces données.
    Il y a peut-être mieux comme solution pour faire ça, je suis pas expert en C++. Mais moi je procède comme cela.

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2002
    Messages : 290
    Points : 325
    Points
    325
    Par défaut
    Logiquement la conception te permet de savoir quelles fonction aurront à être redéfinies par les classes héritantes. N'imprte quelle classe n'est pas destinée à être heritée.

    Les raisons de ne pas declarer une fonction virtual :
    -les performances, un link dynamique c'est une indirection suplémentaire, donc une occasion de se rendre compte que ce que l'on cherche n'est pas dans le cache... De plus le compilo se voit interdit toute tentative d'optimisation type inline...
    -La memoire puisque on ajoute une entrée dans une vTable (ou le mécanisme utilisé par le compilo)... ...sauf cas particulier (déjà vu) ce n'est pas vraiment limitant.

  4. #4
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Y'a une discution plus ou moins sur le sujet:
    http://www.developpez.net/forums/viewtopic.php?t=457190

    Comme l'a dit Gandalf c'est avant tout un problème de conception, pas de C++. Quand tu crées la classes, à priori tu décides si elle est destinée à être utilisée polymorphiquement ou non.

    Une grande différence en C++ avec Java/Python c'est que tu peux manipuler un objet par valeur, après l'avoir instancié sur la pile. Dans ce cas la virtualité ne fonctionne pas, même avec virtual.
    Et puis toutes les classes ne sont pas destinées à être dérivées, en particulier ces fameuses "value class". Pourquoi générer une vtable alors ?
    Exemple avec les conteneurs de la STL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::vector<int> v( 5 );
    cout << v.size(); // virtual n'aurai pas de sens
    Enfin la logique de C++ c'est "paye uniquement pour ce que tu demandes". Pense aux applis embarquées, si la virtualité n'est pas nécessaire dans ta hiérarchie de classes, pourquoi l'imposer ? Sur de petits processeurs embarqués ça peut êrte réellement pénalisant.

  5. #5
    Membre éclairé Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Citation Envoyé par Aurelien.Regat-Barrel
    Une grande différence en C++ avec Java/Python c'est que tu peux manipuler un objet par valeur, après l'avoir instancié sur la pile. Dans ce cas la virtualité ne fonctionne pas, même avec virtual.
    Hum, moi j'ai une classe qui utilise une certaine sorte de polymorphisme.

    C'est à dire que tu considères une classe de base A, qui a des méthodes auxquelles j'y touche pas, et ces méthodes définies une fois pour toutes appellent des autres méthodes, auxquelles j'ai rajouté le mot clé virtual.

    Je construis ensuite une nouvelle classe B qui dérive directement de A.
    Les méthodes virtuelles de A sont ensuite surchargées dans la classe B.

    Quand je crée un objet de la classe B directement avec la pile, et que j'appelle les méthodes ayant été définies pour de bon (au niveau de la classe de base A), eh bien si je n'avais pas mis le mot-clé virtual, les nouvelles méthodes surchargées dans la classe B n'auraient pas été appelées, mais seulement celles de A.

    C'est pas du polymorphisme statique ça, avec pile ?

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #include <iostream>
     
    class A
    {
    	virtual void DoSomething()
    	{
    		std::cout << "C'est la classe A qui parle ici !\n";
    	}
     
    public:
    	void Action()
    	{
    		DoSomething();
    	}
    };
     
    class B : public A
    {
    	void DoSomething()
    	{
    		std::cout << "C'est la classe B qui parle ici !\n";
    	}
    };
     
     
    int main()
    {
    	A a;
    	B b;
     
    	a.Action();
    	b.Action();
     
    	return 0;
    }
    Resultat :

    C'est la classe A qui parle ici !
    C'est la classe B qui parle ici !

    Et si j'avais enlevé virtual, ça ne marcherait pas :

    C'est la classe A qui parle ici !
    C'est la classe A qui parle ici !

    Cet aspect du polymorphisme est rarement abordé j'trouve.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Erreur: Avec sans le virtual, ton exemple marche aussi.

    C'est en les utilisant en tant que "référence sur A" ou "pointeur sur A" que le virtual a une signification...


    Edit: Note pour plus tard : Penser à me racheter des yeux
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    En ce qui me concerne, les virtuals sont là en conséquence des choix de design. Si il apparait qu'un comportement doit être ajusté à un point précis, alors la réalisation de ce point précis (de variabilité) va reposer sur un polymorphisme d'inclusion (à base de fonction membre virtuelle en C++) dans le cadre de hiérarchies de classes.

    Tout mettre en virtual laisse sous entendre que tout peut être supplanté sans risques. Ce qui est loin d'être vrai. Plus souvent, je trouve que des refactorings plus profonds sont nécessaires pour étendre des traitements qui n'avaient pas précisément anticipé l'évolution. Le virtual par défaut n'a donc plus grand intérêt.

    Soit en ce qui me concerne => pas virtual par défaut, virtual si le design me dit que j'en ai besoin. L'amélioration de performance est la cerise sur le gâteau. Cf un autre fil, plutôt récent sur l'impact de la liaison tardive sur les performances.

    Des incompatibilités inhérentes avec les classes à sémantique de valeurs ont été rapellées par mes petites camarades, je n'y reviens pas. Il n'y a pas ici de règle absolu, mais par défaut, ces choses là ne se combinent pas toutes seules sans la moindre précaution.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  8. #8
    Membre éclairé Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Citation Envoyé par Médinoc
    Erreur: Avec sans le virtual, ton exemple marche aussi.

    C'est en les utilisant en tant que "référence sur A" ou "pointeur sur A" que le virtual a une signification...
    Non, sans virtual, l'exemple ne marche pas.

    Testé avec Visual C++ 2005, et Dev-C++.

  9. #9
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Merci beaucoup pour vos réponses très intéressantes. Pour résumer, il semble que vous êtes d'accord pour utiliser virtual seulement si la conception l'impose, et en particulier, il semble parfois souhaitable de ne pas laisser l'utilisateur redéfinir certaines méthodes dans ses classes dérivées. Par ailleurs, une utilisation systématique des méthodes virtuelles semble pénalisante du point de vue des performances sur un petit système embarqué.

    Meilleures salutations

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  10. #10
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Médinoc
    Erreur: Avec sans le virtual, ton exemple marche aussi.

    C'est en les utilisant en tant que "référence sur A" ou "pointeur sur A" que le virtual a une signification...
    Et this est un pointeur... :-)
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est moi qui me suis complètement gouré, j'avais tapé a.DoSomething() au lieu de a.action()...

    Évidemment, sans virtual, A::Action() appelle A:oSomething()...
    En fait, c'est un peu le comportement attendu... Sauf pour un programmeur java...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Erreur "java : could not create virtual machine"
    Par jeanartemis dans le forum Débuter avec Java
    Réponses: 6
    Dernier message: 23/06/2013, 14h14
  2. Réponses: 0
    Dernier message: 22/03/2012, 16h37
  3. [RAD-AD] Erreur "could not create the java virtual machine"
    Par Christophe P. dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 12/12/2011, 11h21
  4. XX:MaxPermSize - "Could not create the java virtual machine"
    Par marcel_kobain dans le forum Autres
    Réponses: 1
    Dernier message: 18/06/2010, 13h04
  5. [DEBUTANT][AXIS]Could not create the Java virtual machine
    Par nezdeboeuf62 dans le forum Services Web
    Réponses: 4
    Dernier message: 30/05/2007, 14h09

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