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 :

Cast d'un type de base vers une classe que j'ai créée


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 31
    Points : 27
    Points
    27
    Par défaut Cast d'un type de base vers une classe que j'ai créée
    Bonjour à tous.

    J'ai un problème de cast : j'ai créé une classe Array (rq : elle est complètement bidon, je ne l'ai créée que pour faire des tests) :
    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
     
    class Array{
    private:
        vector<double> table;
        int dim;
     
    public:
        Array(){
            dim = 0;
        }
        void setTable(vector<double> t){
            table = t;
        }
        vector<double> getTable(){
            return table;
        }
        void setDim(int d){
            dim = d;
        }
        int getDim(){
            return dim;
        }
        double & operator()(int i){
            return table[i];
        }
    };
    Je cherche à savoir comment je peux faire de la conversion de type d'un double vers un Array (par exemple en donnant la valeur du double au membre dim de ma classe).

    Je trouve tous les exemples que je veux pour faire ce genre de manipulation entre deux types que je définis, et d'un type définis vers un type existant (par exemple j'ai réussi à coder le cast Array=>double), mais je n'arrive pas à pondre le cast d'un type prédéfini vers ma classe.

    Est-ce possible ? Si oui comment ?
    Merci de votre aide !

  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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        Array(double d) : dim(d)
        {
        }
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 31
    Points : 27
    Points
    27
    Par défaut
    Merci de la réponse, mais j'ai voulu simplifier ma question et je crois que j'ai un peu déformé ce que je cherche à faire.

    En fait dans la classe Array, j'ai défini un opérateur * qui multiplie deux Array. Je voudrais que ce même opérateur puisse multiplier un Array et un double. Pour ça je voulais que l'appel de 2.*A convertisse le 2. en un Array puis fasse appel à la multiplication des Array. Est-ce possible ?

    Juste pour remarque je ne peux pas (je vous passe les détails de mon implémentation, mais vraiment c'est une contrainte inévitable) définir un autre opérateur * avec des types d'entrée différents.

    Et j'aimerais vraiment pouvoir faire l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Array A;
    // definition de A
    2.*A;
    plutôt que de faire qqch du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Array A;
    // definition de A
    Array B(2.);
    B*A;
    Mais merci quand même JolyLoic de ta réponse.

  4. #4
    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 Simpom Voir le message
    Merci de la réponse, mais j'ai voulu simplifier ma question et je crois que j'ai un peu déformer ce que je cherche à faire.

    En fait dans la classe Array, j'ai défini un opérateur * qui multiplie deux Array. Je voudrais que ce même opérateur puisse multiplier un Array et un double. Pour ça je voulais que l'appel de 2.*A convertisse le 2. en un Array puis fasse appel à la multiplication des Array. Est-ce possible ?
    Oui, si tu definis ton operator* en tant que fonction libre et pas en tant que membre.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 31
    Points : 27
    Points
    27
    Par défaut
    Bon alors je fais ce que j'aurais dû faire dès le départ : qqch de clair !! (dsl pour l'imbroglio précédent...)

    Voilà ce que je voudrais faire :
    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
    39
    40
    41
    42
    43
    44
    45
    template<class T> class Toto{
    private:
        T value;
     
    public:
        Toto<T>(T t=0.){
            value = t;
        }
        void setValue(T t){
            value = t;
        }
        int getValue(){
            return value;
        }
        void operator=(Toto a){
            cout << "(operator =)" << endl;
            value = a.value;
        }
     
        template<class S> friend Toto<S> operator+(Toto<S>, Toto<S>);
    };
     
    template<class S> Toto<S> operator+(Toto<S> a1, Toto<S> a2){
        cout << "(operator +)" << endl;
        Toto<S> a;
        a.value = a1.value + a2.value;
        return a;
    }
     
    int main(int argc, char* argv[]) {
        Toto<int> s(1);
        cout << "value : " << s.getValue() << endl;
     
        Toto<int> t(2);
        cout << "value : " << t.getValue() << endl;
     
        Toto<int> u;
        u=s+t;
        cout << "value : " << u.getValue() << endl;
     
        Toto<int> v;
        v=2+u;
     
        return 0;
    }
    Tout fonctionne sauf la dernière instruction, où il m'insulte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    erreur: no match for 'operator+' in '2 + u'
    Comment m'en sortir ?

  6. #6
    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
    Tu n'avais pas dit que tu etais dans un template.

    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
    template<class T> class Toto{
    private:
        T value;
     
    public:
        Toto(T t=0){
            value = t;
        }
     
        void setValue(T t){
            value = t;
        }
        int getValue(){
            return value;
        }
        void operator=(Toto a){
            cout << "(operator =)" << endl;
            value = a.value;
        }
     
        friend Toto operator+(Toto a1, Toto a2) {
            cout << "(operator +)" << endl;
            Toto a;
            a.value = a1.value + a2.value;
            return a;
        }
    };
    Mais j'ai pas le temps d'expliquer pourquoi.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 31
    Points : 27
    Points
    27
    Par défaut
    Yep merci beaucoup !

    Et si maintenant je veux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Toto<int> s(1);
    Toto<double> t(2);
    Toto<int> u;
    u=s+t;
    Comment (et où) dois-je le coder ?

  8. #8
    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 Simpom Voir le message
    Yep merci beaucoup !

    Et si maintenant je veux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Toto<int> s(1);
    Toto<double> t(2);
    Toto<int> u;
    u=s+t;
    Comment (et où) dois-je le coder ?
    Comment determines-tu le type retourne?
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 31
    Points : 27
    Points
    27
    Par défaut
    Effectivement dans ma petite tête en déclarant u comme un Toto<int> ça permettait de déclarer le type de retour mais effectivement pas...

    Comment dois-je procéder ? Il y a une solution pour que je ne sois pas obligé de préciser le type de retour de mon opérateur ?

  10. #10
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    En C++0X : decltype, tu peux dire que le résultat est du type de (int + double)
    En C++98 : Une classe de traits, mais c'est laborieux, tu dois spécifier ça à la main.
    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.

  11. #11
    Membre éclairé Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Points : 693
    Points
    693
    Par défaut
    Tu peux ne pas utiliser l'opérateur + et définir une fonction qui prend trois paramètres dont son retour (retour par réference);

  12. #12
    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 Simpom Voir le message
    Effectivement dans ma petite tête en déclarant u comme un Toto<int> ça permettait de déclarer le type de retour mais effectivement pas...

    Comment dois-je procéder ? Il y a une solution pour que je ne sois pas obligé de préciser le type de retour de mon opérateur ?
    Il y a differents choix, dont:

    Citation Envoyé par JolyLoic Voir le message
    En C++0X : decltype, tu peux dire que le résultat est du type de (int + double)
    En C++98 : Une classe de traits, mais c'est laborieux, tu dois spécifier ça à la main.
    L'utilisation d'un type proxy comme resultat avec des conversions implicites ou des operateur d'assignation template (voir les expressions template par exemple).

    Ma question etait plus pour pouvoir t'orienter directement vers un choix pertinent.

    Citation Envoyé par MatRem Voir le message
    Tu peux ne pas utiliser l'opérateur + et définir une fonction qui prend trois paramètres dont son retour (retour par réference);
    Le type resultat ne peut pas etre deduit, il devrait etre specifie explicitement ce qui n'est pas desire.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  13. #13
    Membre éclairé Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Points : 693
    Points
    693
    Par défaut
    Le type resultat ne peut pas etre deduit, il devrait etre specifie explicitement ce qui n'est pas desire.
    S'il est passé en paramètre (prend trois paramètres dont son retour) il sera déduit. Ma phrase n'était peut être pas claire...

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 31
    Points : 27
    Points
    27
    Par défaut
    Merci de vos réponses. J'ai réussi à faire ce que je voulais. Bon je force un tout petit peu la chose en demandant que le type de retour de ma fonction soit le type du deuxième argument (c'est le cas d'utilisation le plus probable).

  15. #15
    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,

    Quand je lis
    Citation Envoyé par Simpom Voir le message
    (c'est le cas d'utilisation le plus probable).
    je ne peux m'empêcher d'avoir une série de flash rouges dans la tête pour m'indiquer un danger potentiel

    Je suis peut être trop prudent de nature ou tout à fait parano, mais je ne peux m'empêcher de penser que si c'est le cas "le plus probable", c'est qu'il y a, sans doute, des circonstances où ce ne sera pas le cas

    Je ne remets pas en cause ton analyse, et il est donc tout à fait possible que le type de retour soit, effectivement, toujours identique au deuxième paramètre, mais, si tu as le moindre doute, il serait sans doute intéressant de pousser la réflexion un peu plus loin, soit pour lever le doute, soit pour trouver une solution qui prenne les "cas peu probables / improbables" en compte

    Tu sais, il est généralement admis comme "peu probable" que deux trains se trouvent à contre-sens l'un de l'autre sur un même tronçon de ligne, et, pourtant, quand cela arrive, on compte les morts par dizaines ou par centaines...

    Quelles conséquences pourrait avoir un cas improbable de ton coté
    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

  16. #16
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    En C++0X : decltype, tu peux dire que le résultat est du type de (int + double)
    En C++98 : Une classe de traits, mais c'est laborieux, tu dois spécifier ça à la main.
    En C++98, BOOST_TYPEOF permet de faire comme en C++0X (au comportement chelou sur les references prés mais ici ca ne jouera pas)

  17. #17
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Tu n'avais pas dit que tu etais dans un template.

    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
    template<class T> class Toto{
    private:
        T value;
     
    public:
        Toto(T t=0){
            value = t;
        }
     
        void setValue(T t){
            value = t;
        }
        int getValue(){
            return value;
        }
        void operator=(Toto a){
            cout << "(operator =)" << endl;
            value = a.value;
        }
     
        friend Toto operator+(Toto a1, Toto a2) {
            cout << "(operator +)" << endl;
            Toto a;
            a.value = a1.value + a2.value;
            return a;
        }
    };
    Mais j'ai pas le temps d'expliquer pourquoi.
    Serait-il possible d'avoir l'explication précise, parce que là je sèche.

  18. #18
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Si tu ne mets pas en amie, le système des template fait qu'il ne sauras pas quel fonction appeler en cas de nécessité de conversion implicite (il n'arrivera pas à matcher les paramètre template).

    Le fait de déclarer la fonction en amie force le compilateur à l'utiliser si il peut et donc autorise les conversions implicites.

    NB: Dans la classe, Toto équivaut à Toto<T>, donc la fon,ction amie n'est pas template.

  19. #19
    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
    Citation Envoyé par Flob90 Voir le message
    Si tu ne mets pas en amie, le système des template fait qu'il ne sauras pas quel fonction appeler en cas de nécessité de conversion implicite (il n'arrivera pas à matcher les paramètre template).

    Le fait de déclarer la fonction en amie force le compilateur à l'utiliser si il peut et donc autorise les conversions implicites.

    NB: Dans la classe, Toto équivaut à Toto<T>, donc la fon,ction amie n'est pas template.
    Le fait de déclarer la fonction amie a surtout comme résultat de... la sortir de la portée de la classe, et donc d'en faire... une fonction libre.

    De ce fait, et, comme il s'agit, malgré tout, d'une fonction template (car il s'agit d'une fonction déclarée dans une classe template et manipulant les arguments template ainsi définis), le compilateur choisira cette version s'il s'agit du meilleur "match".

    Ce sera, entre autres, le cas lorsqu'un des paramètres sera de type Toto<XXX>.

    Si l'autre paramètre n'est pas du type Toto<XXX>, il y aura conversion implicite grâce au constructeur de Toto prenant... un XXX comme paramètre (ici: XXX représente n'importe quel type susceptible de représenter une valeur numérique )
    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

  20. #20
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Non koala, ici friend n'a pas pour but de sortir la fonction de la classe.

    Sortir la fonction c'est ce qu'avait fait l'op, et il n'avait pas utiliser friend car il n'avait pas besoin d'accéder à la classe. Cependant ici, le frien est obligatoire pour avoir une fonction bel et bien déclaré.

    Ce n'est pas une fonction template, c'est une fonction amie d'une classe template, la nuance est là. Si c'était une méthode template d'une classe (template ou non) alors la méthode qui correspond au paramètre ne serait déclaré qu'au moment de la compilation (et le match des paramètre devrait être exact). Alors qu'une méthode d'une classe template est déclaré dès qu'une version de la classe à été "utilisé".

    Si tu essays d'appeler une fonction template et que les paramètre ne correspondent pas exactement (à la compilation) alors l'appel échouera, il n'y a pas de conversion implicite possible. Ces conversions ne sont possibles qu'avec des fonctions non-template.

    Le but de friend n'est pas ici de permettre l'accés à la classe, mais d'assurer qu'une fonction est bien déclaré et permettre les conversions implictes.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Importation de données d'une base vers une autre
    Par jiluc dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 30/03/2006, 16h03
  2. Importation d'une base vers une autre
    Par PegasusDream dans le forum Access
    Réponses: 3
    Dernier message: 19/01/2006, 15h15
  3. RMAN : Duplication d'une base vers une autre
    Par Visiteur_33 dans le forum Recovery Manager
    Réponses: 2
    Dernier message: 03/11/2005, 14h40
  4. exporter des objets d'une base vers une autre
    Par RGShoop dans le forum Access
    Réponses: 3
    Dernier message: 07/09/2005, 11h52
  5. [héritage] cast avec le type de base
    Par Lere dans le forum C++
    Réponses: 6
    Dernier message: 16/09/2004, 18h21

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