C++ class Retourner un pointeur via une methode

Résolu
picolo220 Messages postés 18 Date d'inscription dimanche 19 février 2006 Statut Membre Dernière intervention 8 avril 2017 - Modifié le 7 avril 2017 à 16:16
picolo220 Messages postés 18 Date d'inscription dimanche 19 février 2006 Statut Membre Dernière intervention 8 avril 2017 - 8 avril 2017 à 21:54
Bonjour à tous,

Voici mon problème, j'ai créé une classe Piece dans laquelle j'ai créé un attribut pointeur m_position_image :

piece.h
class Piece{
  public :
    Piece(int x, int y, std::string image);
    ~Piece();
    void deplacement(bool haut, bool bas, bool gauche, bool droite);
    bool placement_correct();
    std::string get_image();
    SDL_Rect get_m_position_image();
  private :
    int m_numero_piece;
    int m_x;
    int m_y;
    bool m_placement_correct;
    std::string m_image;
    SDL_Rect *m_position_image;
};


voici les définitions des méthodes dans le fichier cpp :

piece.cpp
Piece::Piece(int x, int y, std::string image):m_x(x), m_y(y), m_image(image){
  m_position_image = new SDL_Rect();
  m_position_image->x = x;
  m_position_image->y = y;

}

Piece::~Piece(){
  delete m_position_image;
}

std::string Piece::get_image(){
  return m_image;
}
SDL_Rect Piece::get_m_position_image(){
  m_position_image = new SDL_Rect();
  m_position_image->x = m_x;
  m_position_image->y = m_y;
  return m_position_image;
}



Voici l'appel que j'aimerai faire dans mon main :

Piece ma_piece(47,47,"img/1.bmp");
SDL_BlitSurface(case1, NULL, ecran, ma_piece.get_m_position_image());


mais la fonction SDL_BlitSurface attend les arguments suivants :
SDL_UpperBlit(SDL_Surface*, SDL_Rect*, SDL_Surface*, SDL_Rect*)


et me retourne donc l'erreur suivante :
cannot convert 'SDL_Rect' to 'SDL_Rect*' for argument '4' to 'int SDL_UpperBlit(SDL_Surface*, SDL_Rect*, SDL_Surface*, SDL_Rect*)'


J'ai bien compris qu'il faut lui fournir un pointeur en 4ème argument, mais j'ai beau retourner les signes * et & dans tous les sens rien n'y fait.

La question que je me pose est la suivante :
Comment retourner un pointeur provenant d'une classe en utilisant une méthode publique
De la même manière j'arrive pourtant bien a retourner l'attribut m_image qui lui n'est pas un pointeur.

Merci d'avance pour votre aide.

Cordialement

6 réponses

cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
Modifié le 7 avril 2017 à 16:16
Bonjour.

Tu as écrit:
SDL_Rect get_m_position_image();

au lieu de:
SDL_Rect* get_m_position_image();


Tout simplement :).

Quelques conseils:
  • Design étrange: un pion ne devrait pas avoir sa position spatiale. Pour moi, c'est au plateau de jeu de posséder des pions et donc leur emplacement.
  • Je marquerais comme const, toutes les méthodes qui ne modifient pas la classe Piece (donc tous les getters déjà).
  • Je mettrais const std::string& au lieu de std::string en argument de ton constructeur (une copie inutile en moins).
  • Quand tu fais un new d'un objet sans argument, il n'y a pas de parenthèse. Donc: "m_position_image = new SDL_Rect;". La parenthèse en plus veut dire autre chose (création d'une fonction qui retourne un SDL_RECT), et tu as de la chance parce que ça passe.
  • Généralement, l'extension d'un fichier header C++ est .hh ou .hpp (le .h c'est pour du C).



Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
0
picolo220 Messages postés 18 Date d'inscription dimanche 19 février 2006 Statut Membre Dernière intervention 8 avril 2017
Modifié le 7 avril 2017 à 23:10
Bonjour cptpingu,

Merci pour ta réponse et pour tes conseils.

J'ai effectivement essayé d'écrire cette version avant celle que j'ai posté :


SDL_Rect* get_m_position_image();


Donc la définition de ma méthode se transforme en :


SDL_Rect Piece::*get_m_position_image(){
m_position_image = new SDL_Rect();
m_position_image->x = m_x;
m_position_image->y = m_y;
return m_position_image;
}


et à ce moment là le compilateur me retourne que m_position_image n'est pas déclaré :

error: 'm_position_image' was not declared in this scope
error: 'm_x' was not declared in this scope
error: 'm_y' was not declared in this scope

Je suppose que cela a à voir avec le fait que la fonction est un pointeur.

Je prend note de tous tes conseils et je suis d'accord avec le fait qu'un pion ne devrait pas posséder sa position spatiale, mais je sais que ce problème de retour de pointeur me bloque depuis longtemps, vu que j'ai un exemple j'aimerai le creuser.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
8 avril 2017 à 00:09
Donc la définition de ma méthode se transforme en :
SDL_Rect Piece::*get_m_position_image(){


Oula, non. Absolument pas. Cette syntaxe n'existe pas.

La bonne syntaxe est:
SDL_Rect* Piece::get_m_position_image() // on devrait même ajouter un const sur la méthode, pour plus de propreté
{
  return m_position_image;
}


Soit dit en passant, à chaque fois qu'on appelle cette méthode, dans ta version tu recrées un nouvel SDL_Rect. La version proposée est plus correcte et fais ce que décrit le nom de la méthode (simplement retourner la variable "position_image").

Tu ne sembles vraiment pas à l'aise avec le notion d'objet, et avec la syntaxe du C++. Peut-être lire un cours t'aiderait ?
https://openclassrooms.com/courses/programmez-avec-le-langage-c
0
picolo220 Messages postés 18 Date d'inscription dimanche 19 février 2006 Statut Membre Dernière intervention 8 avril 2017
8 avril 2017 à 00:36
En fait le code que tu as vu est le résultat de plusieurs essais et prises de têtes, je deviens fou. Et bien que la syntaxe n'existe pas, le compilateur ne m'a rien dit...

Le fait de recréer l'objet SDL_Rect dans la méthode c'était en désespoir de cause :D
Je suis bien conscient qu'il ne doit être créé que dans le constructeur.

J'ai trouvé l'erreur dans ma syntaxe juste après avoir fait ma dernière réponse, je suis vraiment rouillé en C++, mais j'ai compris mon erreur.

J'ai gardé ça au final :


Piece::Piece(int x, int y, std::string image):m_x(x), m_y(y), m_image(image){
m_position_image = new SDL_Rect;
m_position_image->x = x;
m_position_image->y = y;
}
SDL_Rect *Piece::get_m_position_image(){
m_position_image->x = m_x;
m_position_image->y = m_y;
return m_position_image;
}



Concernant le std::string&,

Si je comprend bien tu suggère de fournir à mon constructeur l'adresse de mon objet string plutôt que l'objet en lui même pour éviter qu'il n'en fasse un copie locale dans le constructeur, c'est bien ça?

Mais du coup je ne peux plus appeler mon constructeur comme ça :


Piece piece_1(47,47,"img/1.bmp");


je me retrouve obligé de le passer dans une variable string avant :


string temp = "img/1.bmp";
Piece piece_1(47,47,temp);
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
8 avril 2017 à 02:08
Je ne sais pas si tu es rouillé en C++, mais tu sembles vraiment débuter en conception objet ! (Il y a de gros gros problèmes de design un peu partout).

SDL_Rect *Piece::get_m_position_image(){
  m_position_image->x = m_x;
  m_position_image->y = m_y;
  return m_position_image;
}


Pourquoi réassigner à nouveau x et y ? Ça n'a pas de sens...


Mais du coup je ne peux plus appeler mon constructeur comme ça :
Piece piece_1(47,47,"img/1.bmp");


Bien sur que si tu peux... La référence n'est pas un pointeur, donc tu ne paieras pas la copie du passage au constructeur, mais il y a aura bien une copie vers ton attribut au moment où tu feras: "m_image(image)"
std::string => copie constructeur + copie vers attribut (2 copies)
const std::string& => copie vers attribut (1 copie)
Enfin, "toto" (une chaine "en dure") est bien compatible avec un "const std::string&".

Un design plus propre:
class Piece
{
  public :
    // Déplacement de pieces à faire dans une autre classe qui possède les Pieces
    Piece(int x, int y, const std::string& image);
    ~Piece();
    std::string get_image() const;
    const SDL_Rect* get_position_image() const;
  private :
    std::string _image;
    SDL_Rect _position_image; // Pas besoin de faire un new + delete si on peut avoir l'objet directement...
};

Piece::Piece(int x, int y, const std::string& image)
: _image(image)
{
  _position_image.x = x;
  _position_image.y = y;
}

Piece::~Piece()
{
}

std::string Piece::get_image() const
{
  return _image;
}

const SDL_Rect* Piece::get_position_image() const
{
  return &_position_image;
}

0
picolo220 Messages postés 18 Date d'inscription dimanche 19 février 2006 Statut Membre Dernière intervention 8 avril 2017
8 avril 2017 à 21:54
Merci beaucoup pour tous ces éclairages, je vais pouvoir continuer avec de meilleures bases.
0
Rejoignez-nous