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 :

Problème d'instanciation de classe C++


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Par défaut Problème d'instanciation de classe C++
    Bonjour à tous.
    Voilà j'ai un petit doute et j'aimerais votre avis pour être sur de ne pas faire d'erreur.

    Soit la classe A définit comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class A
    {
    private: int x;
      public: A(); ~A();
    }
    et la classe B et C qui hérite de la classe A :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class B: public A { }
    classe C: public A{}
    Jusque là rien de bien spécial.

    Maintenant, j'ai une fonction de lecture, appelons là Lect(string filename); qui est censé renvoyer un objet dont les fonctions sont dans la classe A.
    Le problème est qu'actuellement, je ne peux définir avec cette fonction que des objets définit par la classe A, mais pas par la classe B et C.

    Que dois-je ajouter lors de la définition de ma fonction pour que je puisse, indépendamment du fait que c'est une instanciation de la classe B ou C, n'avoir qu'une seule et même fonction de lecture, qui utilise donc les fonctions de la classe A mais qui renvoie un objet B ou C.

    Merci d'avance !

  2. #2
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 41
    Par défaut
    Bonjour,
    Si j'ai bien compris, tu as trois classes et tu as une fonction 'à part' qui doit renvoyer l'une des classes. Dans ce cas, la solution qui me semble la plus adapté est de la templater.

    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
     
    class A
    {
            public:
            int x;
            A(){x=1;}
    };
     
    class B : public A
    {
            public:
            B(){x=2;}
    };
     
    class C : public A
    {
            public:
            C(){x=3;}
    };
     
    template<class T>
    T lect()
    {
            T v;
            v.x = 4;
            return v;
    }
     
    int main()
    {
    	A a;
    	B b;
    	C c;
     
    	std::cout << a.x << " " << b.x << " " << c.x << "\n";
     
    	a = lect<A>();
    	b = lect<B>();
    	c = lect<C>();
     
    	std::cout << a.x << " " << b.x << " " << c.x << "\n";
     
    	return 0;
    }

  3. #3
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Bonjour gilims,

    Maintenant, j'ai une fonction de lecture, appelons là Lect(string filename); qui est censé renvoyer un objet dont les fonctions sont dans la classe A.
    Dis moi si je me trompe, la signature correspondrais à ceci?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    A Lect(string filename);
    Si c'est le cas, tu dois utiliser une notion appelée le polymorphisme.
    La fonction Lect(string filename) de A devra être déclarée avec le mot clé "virtual". Tu ne pourras pas renvoyer un objet mais un pointeur vers l'objet car le polymorphisme ne fonctionne que avec des objets dynamiques (Attention à bien faire la destruction de l'objet donc, ou utilise les pointeurs intelligents du standard ou de boost).

    Donc la signature deviendrai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    A* Lect(string filename);
    //ou 
    auto_ptr<A> Lect(string filename);
    //ou
    shared_ptr<A> Lect(string filename);
    Tu devras ainsi redéfinir dans B et C , la fonction Lect(string filename) sans la mot clé "virtual" cette fois-ci.

    Lors de la création de ton objet à renvoyer, tu devras créer l'objet a retourner comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A * pA = new B; // ou new C;
    return pA;
    Il y a d'avantages de renseignements la dessus sur la FAQ:
    http://cpp.developpez.com/faq/cpp/?page=virtual

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Par défaut
    @vingt sens : j'avais déjà essayé les templates, mais il me dit à chaque fois symbol not found !!

    @Astraya : Il y a une légère mésentente. En voulant simplifier le probleme, je me suis surement mal expliqué.

    J'ai une classe, (que l'on va nommer Reader) et qui est charger de lire un fichier. Elle s'instancie simplement en faisant ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Reader MRead(filename);
    La classe reader contient une fonction, appelé Get_Data(), qui est censé lire le fichier et récuperer les données. Ces données sont en réalité des molécules, que l'on diviser en 2 catégories, la catégorie B (protéine par exemple) et la catégorie C (ligand). Ces deux catégories sont définit par mes classes B et C. Ces deux classes héritent de la classe A (la classe molécule), qui définit de façon générique les atomes et les liaisons, pour en ajouter ou en supprimer, bref le standard.
    Ma question c'est comment je peux faire pour définir la fonction Get_Data() une seule fois sans avoir à définir 2 fois cette meme fonction afin de retourner B et C. C'est à dire de pouvoir librement faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B *Proteine = Get_Data(); 
    C *Ligand = Get_Data();
    sans avoir à réécrire 2 fois le code.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Alors le prototype de Get_Data c'est:

    Dans l'implémentation de cette méthode, tu déclare un A*

    Et un peu plus loin de manière conditionnée tu as:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if(<condition>) {
      a = new B();
    } else {
      a = new C();
    }

    Et enfin plus loins:

    Et ça marchera si B et C héritent de A.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Par défaut
    Je crois qu'on va passer au code source , ca marche pas ...
    Voici le message d'erreur : error: invalid conversion from in main.cpp : IChemos::MoleBase*' to 'IChemos::Ligand*'


    Voici mon main.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #include "molereader.h"
    #include "ligand.h"
     
    int main(int argc, char *argv[])
    {
        MoleReader MolRead("/Users/ethane.mol2",MOL2);
     
         Ligand *Mols = MolRead.Read_MOL2();
    cout << Mols->__ToString()<<endl; // Affiche les données de la molécule.
    Le MoleBase.h (classe A dans l'exemple)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class MoleBase
    {
    private :
            vector<Atom*> atoms;			/*!< Contain All Atoms */
            vector<Bond*> bonds;			/*!< Contain All Bonds */
    public:
        MoleBase();
        ~MoleBase();
         void Add_Atom(Atom *_atome);
         void Add_Bond(int _Atom1, int _Atom2, BondType Type);       
     
    };
    Le ligand.h (classe B dans l'exemple)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    #include "molebase.h"
     
    class Ligand:public MoleBase
    {
    public:
        Ligand();
    };
    Le protein.h (classe C dans l'exemple)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include "MoleBase.h"
     
    class Protein:public MoleBase
    {
    public:
        Protein();
    };

    Et enfin le reader :
    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
     
    #include "Protein.h"
    #include "Ligand.h"
     
    class MoleReader
    {
    private:
            std::string		filename;         /*!< Name of the molecule file */
            FILE*		finput;           /*!< Pointer of the file */
            bool		       EOFile;           /*!< END OF FILE */
            FileFormat        format;              /*!< Format */
     
     
     
    public:
            MoleReader(std::string _Filename);
     
            MoleBase* Read_MOL2(bool debug=false);
     
    };

    Et le contenu de la fonction Read_MOL2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    MoleBase* MoleReader::Read_MOL2(bool debug)
    {
        string typemol = "Ligand";
        MoleBase* Mol=NULL;
        if (typemol = "Ligand") Mol= new Ligand();
        // la lecture s'effectue ici
       return Mol;
     
    }
    J'ai essayé ta technique Nudger, mais j'ai du rater quelque chose ...

  7. #7
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Ceci est normal.
    Le principe est simple, l'héritage c'est comme une rock-star, le fils connait son père mais son père connait pas son fils.
    Donc le compilateur peut transformé un fils en père mais il ne peut pas faire du père un fils car le père ne connait pas son fils.

    Tu ne pourras pas obtenir un fils directement comme ça dans ton main.

    Plusieurs solutions, ou tu utilises le polymorphisme, ou tu ajoutes un renseignement dans le père indiquant quel est son fils pour pouvoir le caster.
    Sinon il existe l'idiome CRTP, ou truc de Barton-Nackman qui permet, avec de la programmation générique, d'informer le parent qui est son enfant. Idiome très simple à mettre en œuvre.

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

Discussions similaires

  1. Problème pour instancier une classe
    Par Armulis dans le forum C++
    Réponses: 4
    Dernier message: 29/06/2014, 15h06
  2. Problème d'instanciation de classe
    Par alexxxx69 dans le forum ASP.NET MVC
    Réponses: 6
    Dernier message: 03/11/2011, 15h18
  3. [Framework] Probléme d'instanciation des classe dao et des classe service
    Par daly2009 dans le forum Spring
    Réponses: 1
    Dernier message: 03/11/2010, 14h19
  4. Problème d'instanciation d'une classe
    Par Jahjouh dans le forum C++
    Réponses: 2
    Dernier message: 03/02/2007, 12h50
  5. problème pour instancier une class
    Par gronaze dans le forum C++
    Réponses: 8
    Dernier message: 30/06/2006, 12h21

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