Partage
  • Partager sur Facebook
  • Partager sur Twitter

Classe dérivée reconnue comme abstraite

    21 novembre 2023 à 13:42:46

    Bonjour j'ai pour projet de réaliser un jeu d'echec en C++. Pour celà j'ai créé une classe abstraite Piece et une première classe Fille Bishop (Fou) ainsi : 

    class Piece {
    protected:
        Coordonnees position;
        Player owner;
    public:
        Piece(Coordonnees position, Player owner);
    
        void setPosition(Coordonnees position);
    
        virtual list<Move> getAllMoves(Board board) = 0;
    
        bool sameColor(Piece const &autrePiece);
    
        virtual bool isMoveAuthorized(Board b, Coordonnees dest) = 0;
    
        virtual const type_info& getType() = 0;
    
        virtual unsigned int getValue() = 0;
    };
    Piece::Piece(Coordonnees position, Player owner) : position(position), owner(owner) {
    }
    
    void Piece::setPosition(Coordonnees position) {
        this->position = position;
    }
    
    //TODO : à compléter
    bool Piece::sameColor(const Piece &autrePiece) {
        return false;
    }
    class Bishop : public Piece{
    public:
        Bishop(Coordonnees position, Player owner);
        list<Move> getAllMoves(Board board) override;
        bool isMoveAuthorized(Board b, Coordonnees dest) override;
        const type_info & getType() override;
        unsigned int getValue() override;
    
    };
    #include "Bishop.hpp"
    
    Bishop::Bishop(Coordonnees position, Player owner) : Piece(position, owner) {
    }
    
    
    bool Bishop::isMoveAuthorized(Board b, Coordonnees dest) {
        return false;
    }
    
    list<Move> Bishop::getAllMoves(Board board) {
        return {};
    }
    
    const type_info &Bishop::getType() {
        return typeid(this);
    }
    
    unsigned int Bishop::getValue() {
        return 3;
    }

    La classe Bishop est considérée comme abstraite ce que je ne comprend pas étant donné que toutes les fonctions virtuelles pures sont bien initialisées et que je n'ai pas déclaré de nouvelle fonction virtuelle pure. 

    Coordonnees c = Coordonnees(ligne[2],ligne[1]);
    Bishop b;
    b = Bishop(Coordonnees((int) ligne[2], ligne[1]), white);



    Pouvez vous m'aider à résoudre ce soucis svp ? 






    • Partager sur Facebook
    • Partager sur Twitter
      21 novembre 2023 à 15:00:07

      Ce que je vois : 

      Bishop b;

      ne peut pas compiler, Bishop n'as pas de constructeur par défaut !

      • Partager sur Facebook
      • Partager sur Twitter
      ...
        21 novembre 2023 à 15:56:06

        Meme en écrivant la ligne comme suit : 

        Bishop b = Bishop(c, white);

        Ca ne fonctionne pas. 

        • Partager sur Facebook
        • Partager sur Twitter
          21 novembre 2023 à 17:40:58

          Salut,

          class Bishop : public Piece{ public: list<Move> getAllMoves(Board board) override; bool isMoveAuthorized(Board b, Coordonnees dest) override; const type_info & getType() override; unsigned int getValue() override; };

          Tu n'as pas les même signatures (manque virtual).

          Sauf erreur de ma part, la class Bishop vient masquer les fonctions de sa classe de base, au lieu de les redéfinir.
          en conséquence, elle hérite des fonctions virtuelles pure, qui, n'étant pas redéfinies, rendent la class abstraite.

          Edit: Autant pour moi, il me semblait que le mot clef virtual etait obligatoire.

          PS:

          Player owner;

          Est ce que tu peux nous expliquer le sens derrière ce membre ?
          Aux échecs, une pièce à une couleur, et un joueur joue avec des pièces, pas l'inverse (la pièce n'a que faire du joueur).

          -
          Edité par Deedolith 21 novembre 2023 à 18:25:15

          • Partager sur Facebook
          • Partager sur Twitter
            21 novembre 2023 à 18:00:56

            Deedolith a écrit:

            Tu n'as pas les même signatures (manque virtual).

            Sauf erreur de ma part, la class Bishop vient masquer les fonctions de sa classe de base, au lieu de les redéfinir.
            en conséquence, elle hérite des fonctions virtuelles pure, qui, n'étant pas redéfinies, rendent la class abstraite.

            Si c'était le cas avec override on aurai une erreur il me semble ?

            Il n'est pas nécessaire de répéter virtual dans les classes dérivées il me semble ?.



            • Partager sur Facebook
            • Partager sur Twitter
              21 novembre 2023 à 18:35:02

              RenaudDucrocq a écrit:

              Meme en écrivant la ligne comme suit : 

              Bishop b = Bishop(c, white);

              Ca ne fonctionne pas. 

              Tu n'as pas de constructeur de recopie.
              Ce qui en soit n'est pas une mauvaise chose, vue que les classes Piece (et leurs dérivées) ont clairement une sémantique d'entité, et ne sauraient être ni copiables, ni assignables.

              • Partager sur Facebook
              • Partager sur Twitter
                21 novembre 2023 à 20:21:50

                Ce n'est pas le constructeur de copie qui est appelé dans ce cas, il me semble ?
                • Partager sur Facebook
                • Partager sur Twitter
                  21 novembre 2023 à 21:02:23

                  Constructeur de recopie ou opérateur d'affectation, les deux n'ont pas de sens dans le cadre d'une classe à sémantique d'entité.

                  Bref, c'est l'instanciation qui merdoie.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    21 novembre 2023 à 21:14:30

                    Mais ce n'est pas non plus l'opérateur d'affectation qui est appelé dans ce cas, il me semble ?
                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 novembre 2023 à 13:53:01

                      Bonjour et merci à tous pour vos réponse. D'abord je vais répondre à ce commentaire : 

                      Je suis un tutoriel pas a pas qui veut que les pieces aient en parametre le joueur propriétaire. 

                      Pour la suite j'ai du mal à comprendre ce que je peux faire afin que la classe Bishop soit une classe réelle et non abstraite j'ai logiquement redéfinie les fonctions virtuelles pures de la classe Piece. 

                      Quelle est la différence entre masquer les fonctions et les redéfinir? Comment écrire un constructeur différent de celui que j'ai écrit? Y a t il une solution à tout ce problème ?

                      -
                      Edité par RenaudDucrocq 23 novembre 2023 à 13:54:42

                      • Partager sur Facebook
                      • Partager sur Twitter
                        23 novembre 2023 à 15:48:00

                        Peux-tu donner la ligne de code qui provoque l'erreur et le texte de l'erreur ?
                        • Partager sur Facebook
                        • Partager sur Twitter
                        ...
                          23 novembre 2023 à 17:00:23

                          L'erreur survient dans le constructeur de ma classe board : 

                          #ifndef MAIN_BOARD_HPP
                          #define MAIN_BOARD_HPP
                          
                          #include "Pieces/Bishop.hpp"
                          
                          class Board {
                          private:
                              Player white;
                              Player black;
                              Piece* pieces [2][8];
                          public:
                              Board(const string& fileName, Player white, Player black);
                          
                          };
                          
                          
                          #endif //MAIN_BOARD_HPP
                          #include "Board.hpp"
                          #include <iostream>
                          #include <fstream>
                          
                          Board::Board(const string& fileName, Player white, Player black) : white(white), black(black) {
                              ifstream fichier(fileName);
                              if (fichier){
                                  string ligne;
                                  getline(fichier, ligne);
                                  cout << ligne;
                                  switch (ligne[0]) {
                                      case 'b':
                                          Coordonnees c = Coordonnees(ligne[2],ligne[1]);
                           Bishop b = Bishop(c, white);
                          
                                  }
                          
                              } else {
                                  cout << "ERREUR OUVERTURE DU FICHIER";
                              }
                          }



                          ligne de construction du Bishop.


                          -
                          Edité par RenaudDucrocq 23 novembre 2023 à 17:03:42

                          • Partager sur Facebook
                          • Partager sur Twitter
                            23 novembre 2023 à 17:34:41

                            Donc ligne 14.

                            rouIoude a écrit:

                            ... et le texte de l'erreur ?

                            Et le texte du message ?



                            • Partager sur Facebook
                            • Partager sur Twitter
                            ...
                              23 novembre 2023 à 20:01:29

                              A mon avis,

                              le mieux est que tu envoie tes sources sur une plateforme (GitHub par exemple), et que tu nous refiles le lien.

                              PS: Dans la classe Board, je voit un tableau C-styles (pas bien), d'horribles pointeurs nu (encore moins bien) non initialisés (définitivement pas bien) par le constructeur.



                              -
                              Edité par Deedolith 23 novembre 2023 à 20:04:01

                              • Partager sur Facebook
                              • Partager sur Twitter
                                24 novembre 2023 à 23:55:06

                                Bonjour,

                                Il y a bien une erreur dans le code, une variable ne peut pas être définie après un label. Ca serait plus simple d'avoir le texte de l'erreur!

                                        switch (ligne[0]) {
                                            case 'b':
                                            { // début d'un bloc
                                                Coordonnees  c( ligne[2], ligne[1] );
                                                Bishop  b( c, white );
                                            } // fin du bloc
                                        }
                                • Partager sur Facebook
                                • Partager sur Twitter

                                En recherche d'emploi.

                                  9 janvier 2024 à 12:14:47

                                  Rebonjour à tous j'ai suivi vos conseils et créé un repo Git : https://github.com/RenaudDucrocq/ChessGame.git 

                                  J'ai modifié le tableau de Pieces anciennement en C-style pour utilisé les std::array. 

                                  Et pour finir je vous transmet le code d'erreur que CLION me retourne quand je suis dans la classe board.cpp : 

                                   Allocating an object of abstract class type 'Bishop'

                                  J'ai trouvé et compris l'erreur que j'avais ici ! 

                                  Les classes Piece et Board sont interdépendantes ainsi leurs déclarations bouclent sans jamais être initialisées. La classe Bishop ne peut donc pas profiter de la classe Piece et de ses attributs et est donc considérée comme abstraite.

                                  J'ai résolu le problème en déclarant les classes Pieces et Board dans les classes dépendantes.

                                  Cependant cela ne me semble pas très correct pouvait vous me confirmer que cette correction et la bonne ? 

                                  //
                                  // Created by renaud on 21/11/2023.
                                  //
                                  
                                  #ifndef MAIN_BOARD_HPP
                                  #define MAIN_BOARD_HPP
                                  
                                  #include "Pieces/Piece.hpp"
                                  #include "array"
                                  
                                  class Piece;
                                  class Board {
                                  private:
                                      Player white;
                                      Player black;
                                      array<array<Piece, 8>,2> *pieces;
                                  public:
                                      Board(const string& fileName, Player white, Player black);
                                  
                                  };
                                  
                                  
                                  #endif //MAIN_BOARD_HPP
                                  
                                  //
                                  // Created by renaud on 21/11/2023.
                                  //
                                  
                                  #ifndef MAIN_PIECE_HPP
                                  #define MAIN_PIECE_HPP
                                  
                                  #include <list>
                                  #include <typeinfo>
                                  
                                  #include "Coordonnees.hpp"
                                  #include "Player.hpp"
                                  #include "Move.hpp"
                                  #include "Board.hpp"
                                  
                                  class Board;
                                  class Piece {
                                  protected:
                                      Coordonnees position;
                                      Player owner;
                                  public:
                                      Piece(Coordonnees position, Player owner);
                                  
                                      void setPosition(Coordonnees position);
                                  
                                      virtual list<Move> getAllMoves(Board board) = 0;
                                  
                                      bool sameColor(Piece const &autrePiece);
                                  
                                      virtual bool isMoveAuthorized(Board b, Coordonnees dest) = 0;
                                  
                                      virtual const type_info & getType() = 0;
                                  
                                      virtual unsigned int getValue() = 0;
                                  };
                                  
                                  
                                  #endif //MAIN_PIECE_HPP
                                  



                                  -
                                  Edité par RenaudDucrocq 9 janvier 2024 à 14:13:59

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    9 janvier 2024 à 14:38:42

                                    Ce genre de dépendance cyclique n'est pas forcément bon signe pour la conception.

                                    Cela complexifie leur utilisation.

                                    Peut-être utiliser explicitement des "interfaces" IBoard et/ou IPiece plutôt que des classes abstraites.

                                    Généralement, on ne fait pas l'include du .hpp et la forward définition. Je supprimerai les #include.

                                    Il manque, je pense, pas mal d'utilisation de référence plutôt que des passages par copies.

                                    Evitez les pointeurs nus.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                      9 janvier 2024 à 15:17:08

                                      Je suis d'accord et c'est pour ça que je voulais un avis extérieur quant à cette correction. 

                                      Cependant je suis réticent à l'idée de transformer ma classe Piece en Interface étant donné que le but est d'optimiser l'import des méthodes et attributs communs. 

                                      Quant à l'utilisation de références je ne comprends pas vraiment ce que cela pourrait apporter . 

                                      Je suis ouvert à toute explications afin de m'améliorer. 

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        9 janvier 2024 à 16:33:37

                                        > le but est d'optimiser l'import etc

                                        Le but est d'avoir une conception simple et utilisable de la représentation des données.

                                        "Optimiser l'import", c'est du blabla sans signification.

                                        -
                                        Edité par michelbillaud 9 janvier 2024 à 16:52:39

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          9 janvier 2024 à 16:49:18

                                          Vous parlez d'"optimisation" et vous avez du code comme :

                                          virtual bool isMoveAuthorized(Board b, ...

                                          Où vous clonez littéralement tout votre "Board".

                                          Vous avez pas l'impression de mettre la charrue avant les bœufs ?

                                          Ayez un code clair et maintenable avant de penser "optimisation".

                                          Vous semblez ne pas utiliser les structures de données type array et list de la STL (pas de namespace, #include non "standard"), une raison de ne pas utiliser la STL ? (Autre que vous foutre de l'utilisation des références ; car ne pas les maitriser rend l'utilisation des ces structures standards très "périlleuse").

                                          -
                                          Edité par bacelar 9 janvier 2024 à 17:12:29

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                            9 janvier 2024 à 17:06:48

                                            Ce qui perturbe, C'est qu'il y a bien un 'using namespace std;' mais dans un fichier entête (coordonnees.hpp). Il est déconseillé de nos jour, mais surtout, on ne devrait jamais le trouver dans un fichier entête. Parce que là, il passe sans qu'on se rende compte qu'il est présent.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            ...

                                            Classe dérivée reconnue comme abstraite

                                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                            • Editeur
                                            • Markdown