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 :

Problemes d'heritage en C++


Sujet :

C++

  1. #1
    Candidat au Club
    Inscrit en
    Mai 2007
    Messages
    2
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 2
    Par défaut Problemes d'heritage en C++
    Bonjour

    je dois creer un interface pour gerer des formes geometriques. Pour cela j'ai cree une classe Geometric, classe generique, et des classes "Sphere", "Rectangle",... qui heritent de la classe Geometric.

    Pour avoir une relation du type "A contient B", un des attributs de la classe Geometric est un pointeur vers un autre objet de type Geometric. Je veux donc pouvoir, par exemple, avoir un rectangle inclus dans un autre rectangle, et acceder aux attributs des deux rectangle.

    voici mon code

    declaration des classes:

    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
    class Geometric
    {
    	public:
    		Geometric* contained;
    		Geometric* next;
    		double position[3];
    		double epsilon;
    		Geometric();
    		Geometric(double position[3],double epsilon);
    		~Geometric();
    		void setposition(double position[]);
    		void setepsilon(double epsilon);
    		virtual bool isinside(double vector[3]);
    		void addcontained(Geometric* contained);
    		void addnext(Geometric next);
    		double getepsilon(double vector[3]);
    };
     
    class Rectangle: public Geometric
    {
    	private:
    		double size[3];
    	public: 
    		Rectangle(double position[3],double epsilon,double size[3]);
    		void setsize(double size[3]);
    		bool isinside(double vector[3]);
    };
    fonction addcontained:
    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
     
    void Geometric::addcontained(Geometric* contained)
    {
    Geometric* temp1=this->contained;
     
    if (temp1==NULL)
    	{
    	this->contained=contained;
    	}
    else
    	{
    	Geometric* temp2=temp1->next;
    	while (temp2!=NULL)
    		{temp1=temp2;temp2=temp2->next;}
    	temp1->next=contained;
    	}
    }
    le pointeur next sert a faire une liste d'objets contenus dans le premier.
    Quand je teste ce programme avec le code suivant
    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
     
     
    int main()
    {
    double pos[3]={0.0,0.0,0.0};
    double size[3]={1.0,1.0,1.0};
    double size2[3]={1.0/4,1.0/4,1.0/4};
    double eps=3;
    double eps2=12;
     
    Rectangle rec(pos,eps,size);
    Rectangle rec2(pos,eps2,size2);
     
    Geometric* point_rec=&rec2;
    rec.addcontained(point_rec);
     
    cout<<rec.contained->size[1]<<endl;
     
    return 0;
    }
    Il me reponds que rec.contained est un objet de la classe Geometric et n'as pas d'attributs "size". Or j'ai passe un objet de type "rectangle", et je veux pouvoir acceder a tous ses attributs, pas seulement a ceux de la classe Geometric. Quelqu'un peut me dire ou est mon erreur ?

    Merci

    Pierre

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Bien sur que ça ne fonctionne pas. C'est du C++, pas un vulgaire langage dynamiquement typé.
    Même si l'objet réellement contenu est un rectangle, ton programme ne peut que supposer que c'est un objet geometric (qu'est-ce qu'il se passerait si ce n'était pas un rectangle? -> big erreur, surtout dans un programme C ou C++). Tu peux seulement faire un casting (un dymanic_cast de préfèrence).
    Sinon, tu n'as pas mis de destructeur virtuel à Geometric -> très très pas bien ça.

  3. #3
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Salut,
    il y a deux cas :

    1- Tu veux acceder a des données génériques qui seront dispo dans toutes les formes (genre la compacité):

    tu declare dans Geometric
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virtual float compacity() = 0;
    et dans chaque fille tu l'implemente
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    virtual float compacity()
    {
      return // depend de la forme
    }
    2- si tu as besoin d'acceder a des données spécifiques aux classes filles, tu dois instaurer un systeme de code avec une variable enum
    et tu fais un switch sur la variable et selon la valeur tu cast ton pointeur en l'objet qui correspond et la tu as acces aux methodes filles.

  4. #4
    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 : 50
    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
    Par défaut
    Citation Envoyé par NiamorH
    2- si tu as besoin d'acceder a des données spécifiques aux classes filles, tu dois instaurer un systeme de code avec une variable enum
    Ce système de code existe déjà tout fait en C++, et se nomme dynamic_cast. En plus, la solution fournie en standard a l'avantage de bien fonctionner, ce qui n'est le cas d'aucune solution à base d'énum que j'ai pu voir dans du code provenant de diverses sources, en particulier dans les cas où il y a plusieurs niveaux d'héritage.

    Quoi qu'il en soit, si on se retrouve à devoir faire du code dépendant du type réel de l'objet du côté utilisateur de cet objet, on perd tout l'intérêt du polymorphisme.
    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.

  5. #5
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par JolyLoic
    Quoi qu'il en soit, si on se retrouve à devoir faire du code dépendant du type réel de l'objet du côté utilisateur de cet objet, on perd tout l'intérêt du polymorphisme.
    L'héritage et les virtuelles en C++ permettent d'ajouter facilement des types, mais pas des opérations. Une structure à variant (telle qu'en Pascal, Ada ou dans des langages fonctionnel avec le pattern matching) permet d'ajouter facilement des opérations mais pas des types. On peut aussi ajouter des opérations avec un mécanisme de double dispatch, mais comme il faut d'une part que la hiérarchie l'ait prévue et soit (plus ou moins) figée, les avantages sur un enum décrivant les variants sont faibles.

    Faire une recherche sur "expression problem".

  6. #6
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Citation Envoyé par JolyLoic
    Ce système de code existe déjà tout fait en C++, et se nomme dynamic_cast. En plus, la solution fournie en standard a l'avantage de bien fonctionner, ce qui n'est le cas d'aucune solution à base d'énum que j'ai pu voir dans du code provenant de diverses sources, en particulier dans les cas où il y a plusieurs niveaux d'héritage.

    Quoi qu'il en soit, si on se retrouve à devoir faire du code dépendant du type réel de l'objet du côté utilisateur de cet objet, on perd tout l'intérêt du polymorphisme.

    non non on ne s'est pas compris. Si tu veux utiliser des methodes de classes fille dans une classe mere (ce qui est rare et souvent un probleme de conception), mais que tu ne sais pas à quel type de fille tu es confronté, tu es bien obligé de le déterminer avant de faire ton cast. Le type de cast n'est pas le sujet.

  7. #7
    Candidat au Club
    Inscrit en
    Mai 2007
    Messages
    2
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 2
    Par défaut
    Ok merci de vos conseils.
    J'ai reecris la classe Geometric de maniere a ce que tout les attributs y soit present. pour les classes filles, je redefinis simplement la fonction membre "isinside" qui tient compte de la forme.
    Comme ca ca a l'air de marcher.

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Le probleme est typiquement un probleme qui necessite un double dispatch pour etre resolu proprement. Note si on veut que ce soit de maniere extensible, la technique utilisee dans le pattern visitor ne fonctionne pas car elle necessite qu'une des hierarchies soit fermee (et ici on est avec deux fois la meme hierarchie).

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

Discussions similaires

  1. probleme d'heritage tform1
    Par nosfer dans le forum C++Builder
    Réponses: 5
    Dernier message: 29/05/2006, 13h33
  2. Probleme d'heritage
    Par drcd dans le forum C++
    Réponses: 5
    Dernier message: 28/04/2006, 16h42
  3. [debutant] Probleme d heritage
    Par Treuze dans le forum Débuter
    Réponses: 20
    Dernier message: 21/04/2006, 12h46
  4. probleme d heritage.
    Par ceres02 dans le forum Langage
    Réponses: 11
    Dernier message: 30/03/2006, 14h54
  5. Probleme d'heritage curieux
    Par viddak dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 12/05/2005, 14h58

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