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 :

héritage constructeur et enum class


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 899
    Par défaut héritage constructeur et enum class
    Bonjour,
    Je voudrais pouvoir hériter d'un constructeur d'une classe mère :
    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
     
    using namespace std;
     
    enum class Couleur
     
    { vert, rouge, bleu, orange};
     
    class Forme2
    { 
    	Couleur couleur;
    public :
    	Forme2(Couleur couleur):couleur(couleur)
    	{
     
    	}
    	Couleur getcouleur();
        virtual double calculSurface() = 0;
     
    };
    La classe fille :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #pragma once
    #include "Forme2.h"
    class Rectangle2 :
        public Forme2
    {
        int largeur;
        int longueur;
    Je voudrais pouvoir hériter du constructeur de Forme2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Rectangle2() :Forme2(Couleur couleur) : couleur(couleur)
        {
     
        }
    mais j'ai l'erreur "nom de type non autorisé"
    Si quelqu'un a une idée MERCI

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Le but du constructeur d'une classe est de s'assurer que l'instance de la classe qui est créé soit initialisée avec les bonnes valeurs.

    Si ta classe Forme2 a besoin d'une information de type Couleur pour être "correctement initialisée", il faut -- "tout simplement" -- s'assurer que cette information sera transmise au constructeur de la classe Forme2 par le constructeur de la classe dérivée (Rectangle2, dans le cas présent).

    tu as deux solutions pour y arriver:

    soit, tu t'arranges pour que le constructeur de ta classe dérivée fournisse une couleur "par défaut" au constructeur de ta classe Forme2, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Rectangle2::Rectangle2(): // on implémente le constructeur
        Forme2{Couleur::vert} /* on fait appel au constructeur de Forme2 en 
                               * lui transmettant la couleur vert
                               */
    {
        /* C'est chouette, on n'a plus rien à faire ici */
    }
    Soit tu t'arranges pour que le constructeur de la classe dérivée puisse obtenir la couleur adéquate depuis "ailleurs", sous une forme qui sera alors proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Rectangle2:
        public Forme2 
    {
    public:
        Rectangle2(Couleur couleur); /* on indique qu'il faut l'information de couleur
                                      * pour pouvoir construire notre rectangle
                                      */
        /*  ... le reste */
    };
    Et, l'implémentation du constructeur de Rectangle2 ressemblera à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Rectangle2::Rectangle2(Couleur couleur): /* on implémente un constructeur
                                              * prenant une couleur comme paramètre
                                              */
        Forme2{couleur} /* on appelle le constructeur de forme
                         * en lui transmettant la couleur obtenu
                         */
    On pourrait aussi regrouper les deux possibilités en définissant une couleur "par défaut" qui servirait pourtant de paramètre au constructeur de Rectangle2 sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Rectangle2:
        public Forme2 
    {
    public:
        Rectangle2(Couleur couleur = Couleur::rouge); /* on indique qu'il faut l'information de couleur
                                                       * pour pouvoir construire notre rectangle
                                                       * mais on indique que si aucune valeur n'est transmise,
                                                       * c'est le rouge qui sera utilisé
                                                       */
        /*  ... le reste */
    };
    (l'implémentation de ce constructeur restant la même que dans l'exemple précédent )

    Ce qu'il faut savoir, c'est que la classe de base (Forme2) fait réellement partie intégrante de la classe dérivée (Rectangle2), et que, la partie correspondant à la classe de base dans la classe dérivée devra être construite en priorité pour que l'on puisse construire une instance de la classe dérivée.

    Si la partie correspondant à la classe de base n'est pas construite correctement, la classe dérivée ne pourra purement et simplement pas être construite

    PS:
    1- La directive using namespace std; est totalement inutile dans le cas présent, ne serait-ce que parce qu'il n'y a rien dans le code que tu nous montre qui utilise la bibliothèque standard
    2- En fait, il est largement déconseillé d'utiliser la directive using namespace std; ==>voici pourquoi<==.
    3- Etant donné que la fonction calculeSurface n'aura jamais aucune raison de modifier l'état interne de l'instance de classe à partir de laquelle elle sera appelée, tu devrait la déclarer comme étant une fonction membre (virtuelle) constante, sous la forme de virtual double calculeSurface() const = 0; (dans la classe Forme2, ceci)
    4- N'oublie pas que, à cause de =0, la fonction calculeSurface est considérée comme une fonction virtuelle pure, ce qui a pour effet que la classe Forme2 est considérée comme une "classe abstraite", qui ne pourra pas être instanciée en tant que telle. Pour que tu puisse créer une instance de la classe Rectangle2, alors qu'elle hérite de la classe Forme2, il faudra t'assurer de fournir une implémentation correcte de cette fonction dans la classe Rectangle2, autrement cette classe sera aussi considérée comme abstraite
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 899
    Par défaut
    [QUOTE=koala01;11642077]
    Le but du constructeur d'une classe est de s'assurer que l'instance de la classe qui est créé soit initialisée avec les bonnes valeurs.

    Si ta classe Forme2 a besoin d'une information de type Couleur pour être "correctement initialisée", il faut -- "tout simplement" -- s'assurer que cette information sera transmise au constructeur de la classe Forme2 par le constructeur de la classe dérivée (Rectangle2, dans le cas présent).
    Merci pour ta réponse, voilà ce que j'ai fait au niveau de la classe dérivée en rapport au support de formation qui dit :
    Appel à un Constructeur de la Classe Mère :
    ConstrClasseFille(....) : ConstrClasseMère(....)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Rectangle2(Couleur2 couleur,double largeur, double longueur):Forme2(couleur),largeur(largeur),longueur(longueur)
        {
        }
    Je retrouve bien ici le constructeur de la classe mère(en gras italique) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Rectangle2(Couleur2 couleur,double largeur, double longueur):Forme2(couleur),largeur(largeur),longueur(longueur)
    4- N'oublie pas que, à cause de =0, la fonction calculeSurface est considérée comme une fonction virtuelle pure, ce qui a pour effet que la classe Forme2 est considérée comme une "classe abstraite", qui ne pourra pas être instanciée en tant que telle. Pour que tu puisse créer une instance de la classe Rectangle2, alors qu'elle hérite de la classe Forme2, il faudra t'assurer de fournir une implémentation correcte de cette fonction dans la classe Rectangle2, autrement cette classe sera aussi considérée comme abstraite
    Oui en effet j'ai eu le problème j'ai redéfini la méthode dans Rectangle2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    double Rectangle2::calculSurface()
     
    {
        return largeur * longueur;
    }
    Merci à +

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    C'est ta syntaxe qui n'est pas bonne

    @koala01 a oublié le terme technique : "liste d'initialisation"

    En gros et pour simplifier , lorsque tu appelles 1 constructeur, il faut que lorsque tu arrives à la 1ière ligne du constructeur, que ton objet soit initialisé (et par défaut ces membres seront initialisés à 0)
    Donc il y a cette liste qui commence par : après la définition du constructeur et se termine par l'accolade ouvrante, et avec laquelle tu vas dire quels membres seront initialisés avec quelle valeur.
    On peut initialiser des membres avec la syntaxe parenthèse member(value) et appeler 1 constructeur de la classe mère base_const(params).

    Et c'est pour cette raison que l'initialisation dans le corps du constructeur est redondante

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 899
    Par défaut
    Citation Envoyé par foetus Voir le message
    On peut initialiser des membres avec la syntaxe parenthèse member(value) et appeler 1 constructeur de la classe mère base_const(params).

    Et c'est pour cette raison que l'initialisation dans le corps du constructeur est redondante
    [/QUOTE]
    Merci pour ta réponse, en rapport à ce que tu m'as dit j'ai essayé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Rectangle2(Couleur2 couleur, double largeur, double longueur) :Couleur2(couleur), largeur(largeur), longueur(longueur)
        {
        }
    Mais j'ai l'erreur :"couleur2 n'est ni un membre de données non statique ni une classe de base de la classe Rectangle2", si tu pouvais me donner un exemple
    MErci

  6. #6
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    Code C++ : 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
    // ...
    
    // enum class Couleur { vert, rouge, bleu, orange};
    
    class Rectangle2 : public Forme2
    {
    public :
    
        Rectangle2(Couleur couleur,
                   double  input_largeur,
                   double  input_longueur) : Couleur2 Forme2(couleur), largeur(input_largeur), longueur(input_longueur) {
    
    //      ...
        }
    
    // ...
    
    
    private :
    
        int largeur;
        int longueur;
    };

    Édit : Lire la page de cppreference.com en anglais, Constructors and member initializer lists pour + d'informations
    Par exemple, on peut appeler 1 autre constructeur de la classe et on peut utiliser les accolades au lieu des parenthèses depuis le C++ moderne.

Discussions similaires

  1. Réponses: 7
    Dernier message: 24/02/2011, 13h15
  2. Réponses: 5
    Dernier message: 03/12/2006, 15h55
  3. Réponses: 10
    Dernier message: 20/09/2006, 17h04
  4. [POO]héritage du constructeur de la classe parente
    Par new_wave dans le forum Langage
    Réponses: 7
    Dernier message: 10/03/2006, 14h25
  5. Réponses: 2
    Dernier message: 04/12/2005, 21h10

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