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 :

[Cours][Theorie]classes incapables d'avoir une descendance?


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Par défaut [Cours][Theorie]classes incapables d'avoir une descendance?
    Bonjour,
    On m'assure qu'il est posible de declarer une classe de telle manière qu'elle soit incapable d'avoir une "descendance"?
    Il faudrait pour cela utiliser une classe de base virtuelle....
    Cela dit quelque chose à quelqu'un?
    Merci d'avance

  2. #2
    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
    Par défaut
    Une classe qui n'aurait pas de constructeur non privé, ou dont le destructeur serait privé ? Par contre, une telle classe ne peut s'utiliser classiquement.

    En général, en C++, le simple fait d'avoir un destructeur non virtuel est une documentation indiquant que la classe en question n'est pas conçue pour être dérivée.

    Je ne vois pas trop ce qu'une classe de base virtuelle aurait à voir là dedans.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 41
    Par défaut
    Salut,

    de mémoire un classe virtuelle est une classe ayant au moins une fonction virtuelle pure, comme ci dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class A
    {
       public:
          A() { }
          ~A() { }
       private:
         virtual void my_virtual_function() = 0;
    };
    une telle classe ne peut PAS être instanciée, d'ailleur le constructeur en public n'est pas super utile là...
    Si elle ne peut être instanciée elle ne peut qu'être détivée... Pour avoir une classe non dérivable il faut trouver autre chose. Je regarde dans mes cours pour retrouver quelque chose qui correcpondrait à ça.

    Tarrke

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    un classe virtuelle est une classe ayant au moins une fonction virtuelle pure,
    Non, c'est une classe abstraite. Une classe de base virtuelle est autre chose

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Par défaut
    Le terme employé est bien abstraite dans ce cas-la.
    Le fait d'utiliser une classe de base virtuelle est soit disant un indice pour resoudre ce probleme...
    Mais en fait je dois avouer que j'avais aussi confondu avec une classe abstraite.

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 41
    Par défaut
    Ouuuups

    ma faute !
    bon ben je retourne à mes cahiers et je cherche ce que peut être une classe virtuelle alors.

    Merci de la reprise, ça m'évitera de la refaire celle là !

    Tarrke

  7. #7
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Une classe virtuelle ça n'existe pas, le virtuel de "classe de base virtuelle" s'applique à l'héritage. A savoir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Base
    {
     
    };
     
    class Derivee : virtual Base
    {
     
    };
    Ca permet d'éviter la duplication des données de Base dans Dérivee, si celle-ci en dérive plusieurs fois (oui ça arrive).

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Par défaut
    Oh oui!! C'est pour les structures dites "en diamant", par exemple, non?
    Si ça vous dit quelquechose...
    Soit 4 classes C1 C2 C3 C4
    Si C2 et C3 herite de C1 et si C4 herite de C2 et C3

    Effectivement je ne vois pas en quoi ça concerne mon probleme...

  9. #9
    Rédacteur
    Avatar de bigboomshakala
    Homme Profil pro
    Consultant Web .NET
    Inscrit en
    Avril 2004
    Messages
    2 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Web .NET
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2004
    Messages : 2 077
    Par défaut
    Bonjour,

    pour autant que je sache en C++ on ne peut pas interdire la dérivation d'une classe (contrairement à Java).
    comme le dit Luc Hermitte, si le destructeur d'une classe n'est pas virtuel, c'est qu'a priori elle n'est pas destiné à être dérivé. cela dit on peut le faire quand même, mais gare au polymorphisme.

  10. #10
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    Je reviens sur la question initiale.
    Oui ton truc est possible, en plus d'être la seule façon "programmée" que je connaisse, mais tordu. On t'avait bien aiguillé.
    Je reprends l'idée que j'avais lue dans un post de James (Kanze) sur fclc++. Commentaires dans le code.
    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
    37
    38
    #include <iostream>
    using namespace std;
     
    class CMakeNotInheritable {
    protected:	// private à la place foire tout
        CMakeNotInheritable() {};
    } ;
     
    class CTest 
        : private virtual CMakeNotInheritable  // virtual nécessaire pour interdire
    {
    public:
        virtual ostream & write(ostream & os) const {
    	return os << "CTest" << endl;
        }
    };
     
    class CTest2 
        : public CTest 
        //, private virtual CMakeNotInheritable	// nécessaire pour outrepasser
        						// l'interdiction
    {
    public:
        virtual ostream & write(ostream & os) const {
    	return os << "CTest2" << endl;
        }
        void f() { }
    private:
        int titi;
    };
     
    int main (int argc, char **argv)
    {
         CTest toto;
         toto.write(cout);
         CTest2 tata;
         tata.write(cout);
    }
    L'interdiction est imposée par défaut, mais outrepassable. On paie un vtbl pour l'avoir. Compliqué pour pas grand chose.
    Un commentaire clair et explicite est cencé suffire. Typiquement, il acompagnerait la ligne rappellant la sémantique de la classe, surtout si les objets de cette classe sont censés avoir une sémantique de valeur.
    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...

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Jolie bidouille

    Mais pourquoi est-ce que ça produit l'effet attendu ? Mon compilo me dit que CTest2 ne peut pas accéder au constructeur de CMakeNotInheritable, mais je ne vois pas le rapport entre l'héritage virtuel et le fait qu'il le réclame.

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Par défaut
    Moi aussi je veux bien plusde commentaire car je dois dire que je suis pas tres "avancé" en C++ (je connais le langage mais l'utilise peu...)
    et donc je suis un peu perdu

  13. #13
    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
    Par défaut
    Voici un extrait de la norme qui est nécessaire à la compréhension :

    Citation Envoyé par La norme §12.6.2.6
    All subobjects representing virtual base classes are initialized by the constructor of the most derived class (1.8). If the constructor of the most derived class does not specify a meminitializer for a virtual base class
    V, then V’s default constructor is called to initialize the virtual base class subobject. If V does not have an accessible default constructor, the initialization is illformed.
    A meminitializer naming a virtual base class shall be ignored during execution of the constructor of any class that is not the most derived class. [Example:
    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
    class V {
    public:
    V();
    V(int);
    // ...
    };
    class A : public virtual V {
    public:
    A();
    A(int);
    // ...
    };
    class B : public virtual V {
    public:
    B();
    B(int);
    // ...
    };
    class C : public A, public B, private virtual V {
    public:
    C();
    C(int);
    // ...
    };
    A::A(int i) : V(i) { /* ... */ }
    B::B(int i) { /* ... */ }
    C::C(int i) { /* ... */ }
    V v(1); // use V(int)
    A a(2); // use V(int)
    B b(3); // use V()
    C c(4); // use V()
    —end example]
    En clair, dans le cas d'une classes de base virtuelles se pose la question de quel constructeur pour cette classe appeler.
    Si on a V, dont hérite virtuellement A et B, et C héritant de A et B, A et B peuvent tous deux spécifier un constructeur différent pour leur classe de base V, or comme il n'existe qu'un seul objet V créer, il faut faire un choix.

    Le choix a été fait de ne prendre ni l'appel de A, ni celui de B, mais de demander spécifiquement à l'auteur de C d'expliciter quel constructeur de V doit être appelé.

    Ici, comme l'héritage est privé, CTest peut avoir l'accès qu'il veut à l'interface protected de CMakeNotInheritable, mais ne donne à ses descendants que l'accès à sont interface publique. Donc CTest2 a besoin de spécifier le constructeur de CMakeNotInheritable à utiliser, mais n'en au aucun d'accessible, donc boom.

    C'est un peu le même principe que dans mon post, pour interdire l'héritage, on empêche par l'utilisation de private la classe dérivée de pouvoir spécifier le constructeur de la classe de base qu'elle veut utiliser, mais l'avantage de cette méthode est qu'elle permet de manipuler cette classe classiquement, alors que la mienne demandait à l'utilisateur de passer par des factories pour créer les objets. D'un autre côté, elle est plus lourde.

    Et en tout cas, un commentaire dans le code ou l'absence de destructeur virtuel me semblent les meilleurs solutions.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 760
    Par défaut
    J'ai compris!!! J'ai eu un peu de mal pour tout digerer mais maintenant c'est bon.
    Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 02/01/2015, 13h23
  2. Réponses: 18
    Dernier message: 01/03/2012, 10h34
  3. Réponses: 2
    Dernier message: 05/09/2006, 10h08
  4. Réponses: 2
    Dernier message: 04/05/2006, 23h36
  5. [eclipse][plugin] Comment avoir une fenêtre avec focus
    Par relivio dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 07/04/2004, 15h54

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