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

Langage C++ Discussion :

Tableau de template avec constructeur privé


Sujet :

Langage C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 70
    Points : 57
    Points
    57
    Par défaut Tableau de template avec constructeur privé
    Bonjour, j'ai sûrement un problème de conception mais j'aimerai comprendre pourquoi.

    J'ai défini la classe suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template <class T>
    class Property
    {
    public:
    	Property(unsigned int i_type_mask, T i_value, int i_array_size = -1);
    	~Property(void);
    private:	
    	Property(void);
    };
    et je voudrais faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Property<int> prop1(INT, 10, -1);
    Property<int> prop2(INT, 20, -1);
    Property<int> *prop3 = new Property<int>[2];
    prop3[0] = prop1;
    prop3[1] = prop2;
    Voilà, c'est simple mais ça ne compile pas car le constucteur par défaut est privé (donc je peux pas créer mon tableau prop3) + j'ai le même résultat si j'enlève la déclaration du constucteur par défaut.

    Je sais que je pourrais m'en sortir avec une liste ou un vecteur mais j'aimerai comprendre pourquoi je ne peux pas le faire. Je veux interdire l'utilisation du constructeur par défaut car je ne peux pas initialiser par défaut les variables membres.
    Est-ce qu'il existe un design pattern ou autre chose permettant de faire ça?
    Je pense que c'est possible si ma classe elle-même constuit le tableau (à la manière d'un singleton) mais y'a-t'il une autre solution? est-ce que j'utilise mal les templates?

    merci

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Points : 248
    Points
    248
    Par défaut
    Citation Envoyé par polonain2 Voir le message
    Je veux interdire l'utilisation du constructeur par défaut car je ne peux pas initialiser par défaut les variables membres.
    tu es pourtant bien forcé de le faire ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Property<int> *prop3 = new Property<int>[2];
    Tu crées deux objets de type Property<int> et ils vont utiliser le constructeur par défaut (qui leur sera indisponible car privé) pour s'initialiser.
    Pourquoi ne pas utiliser un vector ?

    Sinon ton problème ne semble pas lié au template.

    EDIT :sinon une solution est de créer une fonction static qui s'occupera d'allouer ton tableau (j'ai un peu simplifier 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
     
    template <class T>
    	class Property
    {
    public:
        Property(T i_value): i(i_value) {}
     
        ~Property(void){}
        T i;
     
        static Property<T> * creerTableau(unsigned int nb){
    	return new Property<T>[nb];
        }
     
    private :
    	Property(): i(0){}
    };
     
    int main(){
     
        Property<int> prop1( 10);
        Property<int> prop2( 20);
        Property<int> * prop3 = Property<int>::creerTableau(2);
     
        cout << "prop1 " << prop1.i << endl;
        cout << "prop2 " << prop2.i << endl;
        cout << "prop3 avant [" << prop3[0].i << " " << prop3[1].i << "]" << endl;
     
        prop3[0] = prop1;
        prop3[1] = prop2;
     
        cout << "prop3 apres [" << prop3[0].i << " " << prop3[1].i << "]" << endl;
     
        delete [] prop3;
     
        return 0;
    }
    qui affiche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    prop1 10
    prop2 20
    prop3 avant [0 0]
    prop3 apres [10 20]

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 70
    Points : 57
    Points
    57
    Par défaut
    sinon une solution est de créer une fonction static qui s'occupera d'allouer ton tableau (j'ai un peu simplifier le code)
    c'est ce que je viens de coder merci.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    En fait, ton problème n'a strictement rien à voir avec les template...

    Ton problème vient du fait que le compilateur ne fournit le constructeur par défaut que si... il ne rencontre aucun constructeur

    Lorsque tu écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class MaClass
    {
        public:
            /*...*/
        private:
            MaClass(){/*...*/}
    };
    Le problème vient de ce que le constructeur n'est accessible qu'aux fonctions de MaClass (par exemple, à un autre constructeur, déclaré publique, celui-là, ce qui est vraiment d'un intérêt plus que douteux ou à une... fonction statique déclarée publique de la classe) et lorsque tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class MaClass
    {
        public:
            MaClass(/* une liste de paramètres */){/*...*/}
        /*...*/
    };
    le problème vient de la "fainéantise" du compilateur qui se dit que, comme tu a défini un constructeur, c'est que tu n'as pas besoin du constructeur "par défaut", et qui décide donc de ne pas l'implémenter

    Si, pour une raison ou une autre, tu as besoin d'un constructeur ne prenant pas d'arguments (entre autres, pour pouvoir créer un tableau "C style"), tu dois donc... le fournir en visibilité publique.

    Cependant, il faut attirer ton attention sur plusieurs points:

    1- Il est, finalement, assez rare de trouver une situation dans laquelle un constructeur ne prenant pas d'argument est intéressant lorsque... l'on décide de fournir un constructeur qui en a besoin.

    La raison est simple: on essaye généralement de respecter le principe du RAII. Si tu estimes devoir passer des arguments au constructeur pour être en mesure de respecter ce principe, il y a au final peu de chances (bien que cela puisse arriver) que tu puisse estimer qu'un objet créé sans les fournir puisse être considéré comme "correctement initialiser", quelles que soient les valeurs que tu donne par défaut.

    2- Il est vraiment préférable d'éviter l'utilisation de tableaux C style, surtout si c'est dans une optique de gestion d'un nombre d'éléments qui n'est connu qu'à l'exécution.

    En effet, dans un tel contexte, on se retrouve facilement à devoir jouer avec la gestion dynamique de la mémoire, et donc à courir le risque de... mal le faire.

    Mais, de plus, nous devons nous rappeler qu'un tableau "C style" ne... connait pas le nombre d'éléments qu'il peut contenir, ce qui nous oblige à coté de cela à maintenir une valeur qui représente... le nombre d'éléments effectifs (si on envisager d'amortir le besoin de réallocation) et une autre qui représente... le nombre maximal d'éléments que l'on peut avoir à un instant T.

    Tout cela nous fait courir le risque, si on n'est pas suffisamment attentif à ce que l'on fait, d'essayer d'accéder... à un élément qui n'existe pas, et donc d'envoyer le système "dans les roses"

    Par chance, le standard nous fournit tout ce qu'il faut avec la classe vector, disponible dans l'espace de noms std grâce à l'inclusion du fichier d'en-tête <vector>, qui gère ces différents aspect de manière tout à fait transparente pour l'utilisateur, et dont il est donc vivement recommande d'user et d'abuser (du moins, lorsqu'il est opportun d'avoir une collection d'objets contigus en mémoire)
    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

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

Discussions similaires

  1. Initialisation d'un tableau avec constructeurs
    Par Kalith dans le forum Langage
    Réponses: 17
    Dernier message: 06/12/2012, 19h40
  2. Template C++ constructeur avec arguments
    Par oc_alex86 dans le forum Débuter
    Réponses: 6
    Dernier message: 06/11/2010, 14h45
  3. Extend d'une classe avec un constructeur privé
    Par aelmalki dans le forum Langage
    Réponses: 5
    Dernier message: 13/03/2010, 11h09
  4. tableau de classe avec constructeur non copiable
    Par pixelou dans le forum Débuter
    Réponses: 3
    Dernier message: 22/02/2010, 23h09
  5. Héritage d'une classe avec constructeur privé
    Par Braillane dans le forum Langage
    Réponses: 13
    Dernier message: 02/09/2009, 11h59

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