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 :

Ambiguité avec la classe base


Sujet :

C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Décembre 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Décembre 2013
    Messages : 10
    Points : 7
    Points
    7
    Par défaut Ambiguité avec la classe base
    salut, j'ai un nouveau problème ennuyant, après succéder a créer la classe Obstacle, j'avais un question : au lieu d'écrire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    RectangleObstacle* obstacle[2]{
        new RectangleObstacle(Vector2f(50, 50), Vector2f(50, 50)),
        new RectangleObstacle(Vector2f(50, 50), Vector2f(150, 150))};
     
    CircleObstacle* obstacle2[2]{
        new CircleObstacle(Vector2f(50, 50), Vector2f(50, 50)),
        new CircleObstacle(Vector2f(50, 50), Vector2f(150, 150))};
    pour quoi je n'écrivais pas quelque chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Obstacle* obstacle[4]{
        new RectangleObstacle(Vector2f(50, 50), Vector2f(50, 50)),
        new RectangleObstacle(Vector2f(50, 50), Vector2f(150, 150)), 
        new CircleObstacle(Vector2f(50, 50), Vector2f(50, 50)),
        new CircleObstacle(Vector2f(50, 50), Vector2f(150, 150))};
    Mais, je trouve l'erreur suivante :
    error C2594: 'argument'*: conversions ambiguës de 'obstacle::RectangleObstacle' en 'const sf::Drawable &'
    mais cette erreur reste même après faire les héritages virtuelles.

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #pragma once
    #include <SFML\Graphics.hpp>
    #include "Object.h"
     
    namespace obstacle
    {
    	class Obstacle abstract :  public virtual Object, public virtual sf::Drawable
    	{
    	public:
    		virtual ~Obstacle(void) = 0 {}
    		void draw(sf::RenderTarget &target, sf::RenderStates states) const {}
    	private:
    		friend class CollisionManager;
    	};
     
    	class ConvexObstacle:
    		public virtual Obstacle
    	{
    	public:
    		ConvexObstacle();
    		ConvexObstacle(ConvexObstacle &source);
    		sf::IntRect GetBoundingBox() const;
    		~ConvexObstacle(){};
    //	   sf::Transformable setPosition(sf::Vector2f &position);
    //	   sf::Transformable setPosition(float x, float y);
    //	   sf::Transformable move(sf::Vector2f &position);
    //	   sf::Transformable move(float x, float y);
    	private:
    		sf::ConvexShape personnalisé;
    		friend class CollisionManager;
    	};
     
    	class CircleObstacle :
    		public virtual Obstacle, public virtual sf::CircleShape
    	{
    	public:
    		CircleObstacle(int radius, sf::Vector2f position, sf::Color fill= sf::Color::White, int pointcount = 30);
    		CircleObstacle(CircleObstacle &source);
    		sf::IntRect GetBoundingBox() const;
    		~CircleObstacle(){};
    	private:
    		sf::CircleShape circle;
    		friend class CollisionManager;
    	};
     
    	class RectangleObstacle :
    		public virtual Obstacle, public virtual sf::RectangleShape
    	{
    	public:
            RectangleObstacle(sf::Vector2f size, sf::Vector2f position, sf::Color fill = sf::Color::White);
            RectangleObstacle(RectangleObstacle &source);
    		~RectangleObstacle();
    		sf::IntRect GetBoundingBox() const;
    		using Obstacle::draw;
    	private:
    		friend class CollisionManager;
    	};
     
    };
    aide s'il vous plait...
    Images attachées Images attachées  

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

    Qu'est-ce qu'il ne faut pas lire quand on a la chance de ne pas être aveugle
    Citation Envoyé par moham104 Voir le message
    Un classe parent ne connait pas l’existence de ses classes enfants donc pour le compilateur faire
    Ca, c'est tout à fait vrai : une classe de base n'a aucune idée des classes qui en dérive


    c'est comme faire ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int * table[4]{ new string("a"), new string("b"), new string("c"), new string("d")};
    Ca, c'est d'autant plus vrai que int est un type primitif et non une classe et qu'il n'y a strictement aucune relation d'héritage entre std::string et le type int.

    Par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Obstacle* obstacle[4]{
        (Obstacle*)new RectangleObstacle(Vector2f(50, 50), Vector2f(50, 50)),
        (Obstacle*)new RectangleObstacle(Vector2f(50, 50), Vector2f(150, 150)), 
       (Obstacle*)new CircleObstacle(Vector2f(50, 50), Vector2f(50, 50)),
       (Obstacle*)new CircleObstacle(Vector2f(50, 50), Vector2f(150, 150))};
    Ca, c'est totalement faux!!!

    Si RectangleObstacle et / ou CircleObstacle héritent bel et bien (de manière publique!) de Obstacle, tu as une relation qui dit que un RectangleObstacle EST-UN Obstacle (idem pour CircleObstacle).

    Tu peux donc parfaitement placer un pointeur vers un objet de type RectangleObstacle (ou CircleObstacle) dans un tableau destiné à recevoir des pointeurs vers des objets de type Obstacles, et tu n'a absolument pas à les transtyper
    Cependant oublie pas que lorsque tu va vouloir réutiliser ces valeurs il faut que tu fasse un autre typecast si tu veux accéder au fonctions spécifique à chaque classe enfant de cette manière là
    Arrghhh...



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ((RectangleObstacle*)obstacle[4])->GetBoundingBox();
    Horreur et calamité !!!

    Citation Envoyé par moham104 Voir le message
    Tu peux aussi utiliser la structures de STL vector pour faire ce que tu fais par exemple faire comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Vector<Obstacle*> m_vecMonConteneur;
    RectangleObstacle * obj = new RectangleObstacle(Vector2f(50, 50), Vector2f(50, 50));
    m_vecMonConteneur.push_back((Obstacle*)obj);
    Et ensuite comme je te l'ai dit auparavant lorsque tu veux y accéder il faut que tu refasse un autre typecast.
    Et le polymorphisme Et le double dispatch C'est fait pour les chiens
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    for(Vector<Obstacle*>::iterator it; it != m_vecMonConteneur.end(); it++)
    {
         ...
         ...  = ( (RectangleObstacle*)(*it))->GetBoundingBox();
         ...
    }
    Mais il est fou!!!

    D'abord, si tu veux absolument utiliser le transtypage, tu ferais bien d'utiliser un transtypage correct: static_cast ou dynamic_cast en fonction des circonstances.

    Ensuite, l'utilisation du transtypage -- quel qu'il soit -- dans cette circonstance particulière est une aberration : C'est le meilleur moyen d'obtenir quelque chose de particulièrement pénible à debugger et de totalement impossible à faire évoluer.

    La clé de la réussite, si tu as vraiment besoin de récupérer le type réel (dynamique) d'un des objets contenu dans une collection de pointeurs vers des objets du type de base, c'est le double dispatch.

    Mais l'idéal reste quand même toujours de profiter au maximum du polymorphisme et d'être en mesure de se contenter des fonctionnalités offertes par le type de base (il faut juste faire attention à garder une certaine cohérence au niveau du type de base... permettre de calculer le rayon d'un obstacle uniquement parce que tu as un CircleObstacle n'a aucun sens ).

    @rami zouari :

    Pour répondre quand même un tout petit peu à ta question.

    déjà, le mot clé abstract n'existe pas ne C++. Le simple fait d'avoir déclaré le destructeur de ta classe Obstacle comme virtuel pur en fait d'office une classe abstraite

    Mais comme ce n'est pas l'origine de ton problème, disons que je te l'indique juste en passant

    Par contre, je me demande réellement pourquoi tu t'esquintes à faire de l'héritage virtuel.

    CircleObstacle hérite de Object et de sf::CircleShape et RectangleObstacle hérite de Object et de sf::RectangleShape. n'est ce pas suffisant, étant donné que je présume (sans connaitre particulièrement en SFML) que sf::CircleShape et sf::RectangleShape héritent tous les deux de sf:rawable, non

    Encore une fois, Encore une fois, la solution passe par le double dispatch : tu te fous pas mal de savoir qu'un obstacle est susceptible d'être tracé! Ce qui t'importe, c'est que les type concrets dérivés de Obstacle sachent qu'ils dérivent d'une classe qui peut passer pour être de type sf:rawable.

    Tu transforme ta fonction draw(/* .. */ ) de Obstacle en fonction virtuelle pure et, dans tous les types concrets qui héritent de Obstacle, comme ils dérivent de toute façons d'une classe pouvant "passer comme étant taçable", tu invoque simplement la fonction draw de cette classe.

    au final, cela te donne quelque chose comme (je simplifie pour n'avoir que ce qui m'intéresse )

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    namespace obstacle
    {
    	class Obstacle :  public Object
    	{
    	public:
    		virtual ~Obstacle(void) = 0 {}
    		virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const = 0
    	private:
    		friend class CollisionManager;
    	};
     
    	class ConvexObstacle:
    		public Obstacle
    	{
    	public:
    		ConvexObstacle();
                    /* AAARGHHH!!! SEMANTIQUE D'ENTITE !!! (*)
    		ConvexObstacle(ConvexObstacle &source);
                    */
    		sf::IntRect GetBoundingBox() const;
    		~ConvexObstacle(){};
                    void draw(sf::RenderTarget &target, sf::RenderStates states) const {
                        // tiens, elle n'hérite vraiment pas d'une classe dérivée de sf::Drawable???
                        // bon, ben on la laisse "ne rien faire :D
                    }
    	};
     
    	class CircleObstacle :
    		public Obstacle, public sf::CircleShape
    	{
    	public:
    		CircleObstacle(int radius, sf::Vector2f position, sf::Color fill= sf::Color::White, int pointcount = 30);  //(**)
     
                    /* AAARGHHH!!! SEMANTIQUE D'ENTITE !!! (*)
    		CircleObstacle(CircleObstacle &source);
                    */
                    void draw(sf::RenderTarget &target, sf::RenderStates states) const{
                        sf::CircleShape::draw(target, states);
                    }
    	private:
    		friend class CollisionManager;
    	};
     
    	class RectangleObstacle :
    		public virtual Obstacle, public virtual sf::RectangleShape
    	{
    	public:
            RectangleObstacle(sf::Vector2f size, sf::Vector2f position, sf::Color fill = sf::Color::White); //(**) 
            /* AAARGHHH!!! SEMANTIQUE D'ENTITE !!! (*)
            RectangleObstacle(RectangleObstacle &source);
            */
    		~RectangleObstacle();
                    void draw(sf::RenderTarget &target, sf::RenderStates states) const{
                        sf::RectangleShape::draw(target, states);
                    }
    	private:
    		friend class CollisionManager;
    	};
     
    };
    (*) !!! ATTENTION!!!

    Les classes qui interviennent dans une hiérarchie de classes ont, par nature, sémantique d'entité et ne devraient en aucun cas être copiables ou affectable (le constructeur de copie et l'opérateur d'affectation devrait être désctivés ).

    Je te laisses un peu chercher par toi même comment il faut t'y prendre

    (**) Comme je présumes que les arguments que tu transmet à tes constructeurs ont pour but de permettre la construction des objets de types sf::XXshape, n'oublie pas d'invoquer le constructeur "qui va bien" de ces types dans la liste d'initialisation de tes constructeurs

    @moham104 : Ne te sens pas attaqué personnellement par le ton de mon message. Il n'a absolument pas l'intention de te froisser. Mais ma réaction était à peu près à hauteur des imbécillités que tu as écrites et, si cela te permet d'en apprendre un peu plus, ce sera déjà ca de gagner
    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

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2011
    Messages : 27
    Points : 34
    Points
    34
    Par défaut
    J'ai effacé mes messages, au cas où quelqu'un voulais savoir à qui faisait référence koala01 vue que c'était remplis d'imbécilité . Je ne veux pas confondre les débutants qui veulent bien apprendre et ne pas apprendre à moitié comme moi

  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
    Citation Envoyé par moham104 Voir le message
    J'ai effacé mes messages, au cas où quelqu'un voulais savoir à qui faisait référence koala01 vue que c'était remplis d'imbécilité . Je ne veux pas confondre les débutants qui veulent bien apprendre et ne pas apprendre à moitié comme moi
    J'espère que tu n'est pas vexé...

    Ce n'était très certainement pas le but de mon intervention.

    Dis toi que tout le monde en a écrit et parfois des bien pires que toi à ses débuts (et je ne fais certainement pas exception ), et que c'est normal dans le sens où le langage est particulièrement complexe.

    Je trouve dommage que tu aies "sabordé" ton message de la sorte, car, même si l'on dit parfois des erreurs manifestes, je crois qu'il faut savoir les assumer jusqu'au bout. Et, qui sait, en rire quand on retombe dessus plusieurs années après.

    Saches au passage que, si je le voulais vraiment, je pourrais :
    1. refaire apparaître le message (le privilège du modérateur )
    2. te donner un avertissement pour sabotage de discussion
    Mais comme je suis malgré tout de bon humeur, qu'il n'entre absolument pas dans mes intentions d'entrer en conflit avec toi, et qu'ils sont cités à peu près dans leur intégralité je vais être bon prince et ne faire ni l'un ni l'autre...

    Ce qui ne veut pas dire qu'un modérateur un peu plus stricte passant par là ne le fera pas
    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

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2011
    Messages : 27
    Points : 34
    Points
    34
    Par défaut
    Je ne crois pas avoir saboté quoi que ce soit, seulement parce que moi même des fois j'ai rencontré des messages dans des forums qui m'ont rendu confus donc je crois que je ne voulais pas faire ça à quelqu'un d'autre et non je ne suis pas vexé je suis très d'accord avec ce que tu a dis j'ai pas réfléchis vraiment comme il faut avant de poster mon message.

    Cependant ça me permet prochain fois de m'assurer que l'information que j’écris est vraie avant de le poster.

    Cependant si tu trouve que ça serait pertinent de faire réapparaitre mes messages tu peux le faire j'ai rien contre ça j'en fais des erreurs pareil au travail avec des collègues qui ont beaucoup d'années d'expérience et ils me corrigent et j'aime ça parce que comme tu le dis ça m'aide à apprendre encore plus.

  6. #6
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Comme le dis koala01, il y à un problème au niveau de ta hiérarchie de classes.

    J'évite au maximum l'héritage multiple car j'arrive jamais à faire quelque chose de propre avec, mais je verrais bien un truc du genre
    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
    namespace obstacle
    {
     
    	class Obstacle : public Object {
    	public:
    		virtual ~Obstacle() { }
    		virtual const sf::Drawable& toDrawable() const = 0;
    		virtual sf::Drawable& toDrawable() = 0;
    		virtual sf::IntRect GetBoundingBox() const = 0;
    	private:
    		friend class CollisionManager;
    	};
     
    	template <class Base>
    	class ObstacleImpl : public Base, public Obstacle {
    	protected:
    		template <class... Args>
    		ObstacleImpl(const Args&... args): Base(args...) { }
    	public:
    		virtual ~ObstacleImpl() { }
    		const sf::Drawable& toDrawable() const { return *this; }
    		sf::Drawable& toDrawable() { return *this; }
    	};
     
    	class ConvexObstacle : public ObstacleImpl<sf::Drawable> {
    		virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const {
    			// ...
    		}
    		// ...
    	};
     
    	class CircleObstacle : public ObstacleImpl<sf::CircleShape> {
    		// ...
    	};
     
    	class RectangleObstacle : public ObstacleImpl<sf::RectagleShape> {
    		// ...
    	};
     
    }
    Qui permet d'utiliser des Obstacle en tant que sf::Drawable via un appel à Obstacle::toDrawable.
    (code non testé)

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Décembre 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations forums :
    Inscription : Décembre 2013
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Merci koala et iradrille, mon problème est résolu...
    pour Mohammed, ton message n'a aucun sens...
    comme même merci pour vos aides les trois

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 25/11/2008, 11h11
  2. Réponses: 0
    Dernier message: 04/09/2008, 19h43
  3. Réponses: 7
    Dernier message: 05/10/2004, 13h44
  4. [C#][WebServices] Appel methode avec une classe en paramètre
    Par bran_noz dans le forum Windows Forms
    Réponses: 6
    Dernier message: 10/09/2004, 16h41
  5. [Débutant][Conception] Erreur avec une classe interne
    Par Devil Redneck dans le forum Général Java
    Réponses: 5
    Dernier message: 11/06/2004, 15h45

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