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 :

probleme surcharge [] sur template


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Flutter/java/windev/php/javascript
    Inscrit en
    Octobre 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Flutter/java/windev/php/javascript
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 87
    Par défaut probleme surcharge [] sur template
    bonjours, je code actuellement une classe template contenant un vecteur de class. celui ci tourne bien mais pour l'ameliorer j'aurais aimer surcharger l'operateur[] pour utiliser:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    montemplate<maClass*> m(2);//créé un template de deux éléments
    m[0] = (maclass*) unElement;
    m[1] = masousClass*) unAutreelement;
    pour ce faire j'ai ecris ceci:

    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
    template<class T>
    class Vector{
    	public:
    		Vector();
    		Vector(int);
    		~Vector();
     
    		void add(T data);
    		int size() {return nbrElement;}
    		T operator[](int);
    		void supElem(int);
     
    	private:
    		Noeud<T> *data;
    		int nbrElement;
     
    		Noeud<T>* nodeAt(int index);
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class T>
    T Vector<T>::operator[](int index)
    {
    	return nodeAt(index)->getData();
    }
    mais lors de la compilation j'obtiens cette erreur:
    error: lvalue required as left operand of assignment
    si je remplace mon template par un pointeur simple de maclass cela fonctionne.


    maintenant si au lieu de déclarer mon vecteur comme ceci: Vector<maclass*>
    je le declare comme cela: Vector<maclass>
    l'erreur disparaît (il utilise le constructeur de copie donc), or le but et ici de n'utiliser que des pointeurs pour stocker, modifier et relire des valeurs restant juste. (et donc modifié a partir du pointeur)

    voila, si quelqu'un a une idée... moi je comprends pas trop pourquoi il ne copie pas l'adresse du pointeur...

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Une référence en retour tu mettras si la valeur changer tu voudras.
    Une version avec référence const tu définiras si tu veux lire la valeur d'un objet const


    (à la volée à partir de ton code) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<class T>
    class Vector{
    	public:
    	 T& operator[](int);
             T const & operator[](int) const;

  3. #3
    Membre confirmé
    Homme Profil pro
    Flutter/java/windev/php/javascript
    Inscrit en
    Octobre 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Flutter/java/windev/php/javascript
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 87
    Par défaut
    cela implique de déclarer vector<class> et non vector<class*> du coup parce que lui proposer de retourner T& ne fonctionnera jamais si T est un pointeur.
    j'aimerai pouvoir garder cette configuration la. Je me demande pourquoi dans la commande:

    vector[x] = class*

    donc T* = T* il me renvois cette erreur... sinon je ferais une copie en rentrant dans le vecteur puis le reste par référence...

  4. #4
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    Citation Envoyé par kranagard Voir le message
    retourner T& ne fonctionnera jamais si T est un pointeur.


    vous n'avez pas compris la réponse de 3DArchi, ni le message du compilateur

    une affectation est une forme L = R, où L est une lvalue et non une value, et donc par exemple une variable et non 123

    l'operator[] doit pouvoir être utilisé pour lire une valeur mais aussi pour en modifier une => il doit rendre une référence et non une valeur
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  5. #5
    Membre confirmé
    Homme Profil pro
    Flutter/java/windev/php/javascript
    Inscrit en
    Octobre 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Flutter/java/windev/php/javascript
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 87
    Par défaut
    je n'ai pas du comprendre effectivement.

    je sais que L = R, j'ai cherché (et trouvé) la définition d'une Lvalue et c'est justement cela que je ne comprend pas.


    j'ai cela:

    avec T = maClass*

    donc la valeur de retour n'est pas un valeur mais bien un pointeur dans ce cas.

    si je modifie ma méthode et qu'elle renvoie T&, le compilateur me râle dessus disant que j'ai maClass*& au lieu de maClass.

    je ne vois pas trop comment faire pour qu'il le prenne sans modifier la valeur de T (qui est un pointeur dans ce cas) en le passant par valeur.



    note que je peux toujours a la déclaration passer maClass, gérer tout par pointeur/référence dans mon vecteur et retourner la référence dans ce cas. mais du coup l'utilisateur devra déclarer





    /*************edit************************/

    je crois que je commence à comprendre, effectivement ça a l'air de répondre parfaitement à ma question, me reste maintenant à tester cela.
    merci

  6. #6
    Membre confirmé
    Homme Profil pro
    Flutter/java/windev/php/javascript
    Inscrit en
    Octobre 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Flutter/java/windev/php/javascript
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 87
    Par défaut
    j'ai un petit problème lors de l'implémentation, je le comprends, mais je ne comprends pas d'où il vient...

    j'ai modifié ce qu'il fallait pour pouvoir déclarer la surcharge de l'opérateur de manière viable (sans variable temporaire ou autre)

    je vais mettre un poil plus de code histoire que se soit plus clair.
    donc voici mon "Nœud", c'est lui qui contient les données et créé la liste chaînée.

    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
    template<class T>
    class Noeud{
    private:
        T data;
        Noeud<T> *next;
    public:
        Noeud();
        Noeud(T Elem);
        ~Noeud();
        T getData();
        void setData(T _data);
        Noeud<T>* getNext();
        void setNext(Noeud<T> *_noeud);
     
    };
    et voici un bout de mon vecteur:

    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
    template<class T>
    class Vector{
    	public:
    		Vector();
    		Vector(int);
    		~Vector();
     
    		void add(T data);
    		T get(int);
    		int size() {return nbrElement;}
    		T& operator[](int);
    		void supElem(int);
     
    	private:
    		Noeud<T> *data;
    		int nbrElement;
     
    		Noeud<T>* nodeAt(int index);
    };
     
    template <class T>
    T& Vector<T>::operator[](int index)
    {
    	return nodeAt(index)->getData();
     
    }
    j'ai donc, dans le cas d'un T = maclass*, nodeAt(...)->getData() qui me retourne un T. celui-ci étant pris par référence et retourné par la fonction.
    jusque la logique. mais si T n'est plus un pointeur j'ai getData() qui me retourne une copie et donc l'erreur suivante à la compilation. (que le cas soit utilisé ou non d'ailleurs)

    error: invalid initialization of non-const reference of type ‘maClass*&’ from a temporary of type ‘maClass*’
    j'ai pensé a faire retourner a getData() un T* (donc pointeur de pointeur dans la majorité des cas), ce qui, je pense pallierait à ce problème mais entraînerai des modification sur l'ensemble des classes dépendante de Nœud étant fonctionnel actuellement. (ce qui est long mais faisable)
    Voyez vous une autre solution?


    ps: je ne retourne pas la référence parce que data peut être égal à NULL dans le cas d'une déclaration de Vector à taille prédéfinie;

    pps: cette erreur est déclarée sur cette ligne:
    monVec[0] = &monObjetDeMaClass;

  7. #7
    Membre confirmé
    Homme Profil pro
    Flutter/java/windev/php/javascript
    Inscrit en
    Octobre 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Flutter/java/windev/php/javascript
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 87
    Par défaut
    j'ai du mal à me mettre en tête que même avec T étant un pointeur je joue avec des objets... mais ça commence à rentrer.

    je crois que j'ai trouvé ce qui n'allait pas:

    en fait je déclare mon vecteur comme ceci:

    Vector<maClass*> vec;

    mais je veux y placer des maClasseFille* et maClassPetiteFille*. du coup le passage par référence me sort un seg fault lors de la copie (parce qu'il s'agit d'une copie avec la référence). n'y a-t-il pas un moyen pour que l'operateur[] retourne un pointeur et que celui-ci soit pris comme lvalue?

  8. #8
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    vous vous compliquez la vie, un Vector<X> doit contenir des X, pas des X *, le seul changement par rapport à votre (ancien) code étant T data; et non T *data

    si vous voulez y stoker des int vous utilisez un Vector<int>, si vous voulez stoker des maClass* alors un Vector<maClass*> etc
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  9. #9
    Membre confirmé
    Homme Profil pro
    Flutter/java/windev/php/javascript
    Inscrit en
    Octobre 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Flutter/java/windev/php/javascript
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 87
    Par défaut
    c'est pas faut ça... j'ai toujours eu tendance à me compliquer la vie...

    je vais reprendre mon code avec cette optique, ça me parait plus juste effectivement.

    mais le problème reste le même non?
    j'aimerai pouvoir utiliser par la suite des dynamic_cast() pour récupérer mes données (plutôt les tester, voir en fonction de ce qui est présent ou non, ce que je fais) ne dois-je donc pas retourner un pointeur?

    enfin en attendant je vais refaire tout ça. merci beaucoup deja pour tout ce que j'ai appris depuis hier. les templates c'étaient vraiment une tache noir sur le cpp pour moi.

  10. #10
    Membre confirmé
    Homme Profil pro
    Flutter/java/windev/php/javascript
    Inscrit en
    Octobre 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Flutter/java/windev/php/javascript
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 87
    Par défaut
    effectivement, en 5 minutes j'ai fais un truc propre et qui tourne... merci énormément franchement, je partais de plus en plus loin dans la complexité alors que c'était simple à faire...

    je n'ai plus que le problème du dynamic_cast() maintenant.

    j'ai donc:

    et j'aimerai faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        if((vi = dynamic_cast<maClassFille*>(Monde[i])))
    qui pour le moment est réalisé comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        if((vi = dynamic_cast<maClassFille*>(&(Monde[i]))))
    ce qui me retourne à tous les coups false vu que Monde[i] est une référence de la classe mère.

    /***************EDIT**********/
    oh mais je viens de me souvenir que vous m'aviez donné deux méthodes, une de lecture et une de modification.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		T& operator[](int);
    		T const * operator[](int) const;
    n'est-il pas possible de modifier la seconde en T const * operator[](int) const
    et de forcer son utilisation dans ce cas? (parce que le fichier trace me montre que la première méthode est utilisée dans les deux cas.)

  11. #11
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    si vous faite un Vector<classeMere> alors celui-ci contiendra que des classeMere, si vous mettez dedans une instance de classe fille celle-ci deviendra une instance de classe mère lors de la recopie dans le vecteur

    si vous voulez stoker des instances de différentes classes il faut impérativement passer par des pointeurs, donc Vector<classeMere *>
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par kranagard Voir le message
    /***************EDIT**********/
    oh mais je viens de me souvenir que vous m'aviez donné deux méthodes, une de lecture et une de modification.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		T& operator[](int);
    		T const * operator[](int) const;
    n'est-il pas possible de modifier la seconde en T const * operator[](int) const
    et de forcer son utilisation dans ce cas? (parce que le fichier trace me montre que la première méthode est utilisée dans les deux cas.)
    Les deux surcharges devraient avoir le même type retour (au const près) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    T& operator[](int);
    T const & operator[](int) const;
    Je ne comprend pas ton problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Vector<Base*> vect;
    // [remplissage]
    Derivee *p_d = dynamic_cast<Derivee*>(vect[0]); // OK !
    // ou
    Derivee const*p_d = dynamic_cast<Derivee const*>(vect[0]); // OK !
    Ca doit compiler avec les opérateurs [] retournant des références.

    Remarque annexe : l'utilisation de dynamic_cast peut relever un problème de conception.

Discussions similaires

  1. [delphi6]probleme dbgrid sur un tpagecontrol
    Par macadam314 dans le forum Bases de données
    Réponses: 2
    Dernier message: 10/04/2005, 15h54
  2. Probleme "onmouseout" sur IE seule
    Par softflowe dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 06/10/2004, 14h04
  3. Probleme install sur RedHat
    Par delph_b dans le forum Installation
    Réponses: 5
    Dernier message: 27/05/2004, 09h09
  4. Réponses: 3
    Dernier message: 17/05/2004, 17h28

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