Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Utiliser le constructeur par défaut d'une classe pour remplir un vector.  (Lu 3066 fois)

0 Membres et 2 Invités sur ce sujet

Enzo76

  • Newbie
  • *
  • Messages: 5
    • Voir le profil
Bonjour à tous,

Je viens à vous car j'ai un petit problème, je vous explique la chose : j'ai créé une classe FORME qui initialise tout ses attributs à des valeurs aléatoires dans son constructeur par défaut :
FORME::FORME()
{
        if(!myImage.LoadFromFile("avion.bmp")) // Si le chargement a échoué
    {
        cerr<<"Error during import avion"<<endl; // On affiche l'erreur
    }
    else // Si le chargement de l'image a réussi
    {
        myDX = Randomizer::Random(1,5);
        myDY = Randomizer::Random(1,5);
        myImage.CreateMaskFromColor(Color::Black);
        mySprite.SetImage(myImage);
        mySprite.SetPosition(Randomizer::Random(100,500),Randomizer::Random(100,500));
    }
}

J'ai ensuite créé une seconde classe qui contient toutes ces formes dans un vector :
class TTES_LES_FORMES
{
    public:
          ...

    private:
        std::vector<FORME> vect_f;
};
Le constructeur de cette seconde classe me permet de définir le nombre de "FORME" dans ce vector en faisant simplement
TTES_LES_FORMES formes(nb_cibles);
dans le main.
Venons en au problème maintenant, j'ai essayé de faire un resize(3) de ce vector cependant la fonction resize utilise le constructeur par défaut pour créer la première forme et ensuite le constructeur de copie pour toutes les autres (d'après ce que j'ai testé et compris en fouillant un peu sur le net  ;D). Je me retrouve donc avec trois formes qui ont les mêmes attributs alors que j'aimerais qu'ils soient différents pour chaque forme.

Une petite idée de comment faire sans les pointeurs?  :o

Merci de m'avoir lu.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #1 le: Décembre 19, 2012, 10:27:27 am »
C'est un peu plus précis que ça : le vecteur ajoute des copies de l'élément que tu passes en paramètre à la fonction resize. Par défaut (si tu n'en passes pas), c'est une instance construite par défaut qui est utilisée.

Bref, la solution est extrêmement simple (t'as pas trop dû te remuer les méninges ;D) :
for (int i = 0; i < n; ++i)
    v.push_back(FORME());
Laurent Gomila - SFML developer

Enzo76

  • Newbie
  • *
  • Messages: 5
    • Voir le profil
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #2 le: Décembre 19, 2012, 10:49:35 am »
Merci beaucoup, c'est la solution à laquelle j'avais pensé et que j'ai proposé à mon prof (je réalise un jeu dans le cadre de mon projet tutoré  :D) et il m'a indiqué de plutôt utiliser resize mais au final je pense qu'il n'aura pas le choix.  :P
Une dernière question, du coup j'ai mes trois formes cependant j'ai ces fameux carrés blancs qui s'affiche à la place des sprites, c'est parce que je charge l'image, au lieu de la copié, à chaque fois que je créé une nouvelle forme, c'est ça?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #3 le: Décembre 19, 2012, 11:05:57 am »
Pas exactement. C'est parce que lorsqu'une FORME est copiée, la copie possède une nouvelle image (qui est une copie de l'image de la FORME originale, mais une nouvelle image quand même). Or son sprite continue à pointer vers l'image de la FORME originale, au lieu de pointer sur sa propre image.

La solution est d'écrire le constructeur par copie :
FORME::FORME(const FORME& forme)
    : myImage(forme.myImage)
    , mySprite(forme.mySprite) // là, mySprite pointe vers forme.myImage
    , ...
{
    mySprite.SetImage(myImage); // mySprite pointe maintenant vers myImage
}
 
Laurent Gomila - SFML developer

Enzo76

  • Newbie
  • *
  • Messages: 5
    • Voir le profil
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #4 le: Décembre 19, 2012, 11:53:44 am »
Merci beaucoup pour toutes ces réponses.
Le constructeur par copie est-il obligatoire? J'ai un autre problème car dans mon jeu j'ai besoin de supprimer des fomes dans ce vector. Par conséquent si je supprime une forme qui précède une forme générée par le constructeur de copie, le constructeur n'aura plus rien à copier et la forme affichera un carré blanc, de même pour toutes celles qui suivent non?  :o C'est en tout cas ce qu'il se produit...  :-\
Par la suite j'aimerais ne pas afficher la même image sur toutes les formes. Je souhaiterais joindre une image aléatoire à chaque forme. J'hésite à me lancer dans un gestionnaire d'image ou serait-il plus simple de charger toutes les images (4 ou 5 images) dans le constructeur et les joindre ensuite?  ;D

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #5 le: Décembre 19, 2012, 11:59:20 am »
Citer
Le constructeur par copie est-il obligatoire?
Ici oui, puisque le constructeur par copie généré par le compilateur ne fait pas ce que tu souhaites.

Citer
J'ai un autre problème car dans mon jeu j'ai besoin de supprimer des fomes dans ce vector. Par conséquent si je supprime une forme qui précède une forme générée par le constructeur de copie, le constructeur n'aura plus rien à copier et la forme affichera un carré blanc, de même pour toutes celles qui suivent non?
Non. Lorsque tu supprimes un élément du vecteur, les éléments suivants sont déplacés pour boucher le trou. Or le déplacement utilise le constructeur par copie, donc ce problème sera résolu aussi lorsque tu auras écrit ce dernier correctement.

Citer
Par la suite j'aimerais ne pas afficher la même image sur toutes les formes. Je souhaiterais joindre une image aléatoire à chaque forme. J'hésite à me lancer dans un gestionnaire d'image ou serait-il plus simple de charger toutes les images (4 ou 5 images) dans le constructeur et les joindre ensuite?
Si la seconde option ne présente aucune difficulté, pourquoi te lancerais-tu dans l'écriture d'un gestionnaire d'images ?
Laurent Gomila - SFML developer

Enzo76

  • Newbie
  • *
  • Messages: 5
    • Voir le profil
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #6 le: Décembre 19, 2012, 12:19:16 pm »
Citer
Si la seconde option ne présente aucune difficulté, pourquoi te lancerais-tu dans l'écriture d'un gestionnaire d'images ?

Je pensais que mon problème venait de la copie d'image et que du coup en faisant un gestionnaire d'image ça aurait résolu mon problème.  ;D

Citer
Non. Lorsque tu supprimes un élément du vecteur, les éléments suivants sont déplacés pour boucher le trou. Or le déplacement utilise le constructeur par copie, donc ce problème sera résolu aussi lorsque tu auras écrit ce dernier correctement.

Il me semblait bizarre aussi de laisser des trous dans le vecteur mais c'est la conclusion que j'ai faites (un peu hâtive certes ;D) lorsque j'ai vu que les sprites disparaissaient. Je pensais pourtant avoir écrit le copy constructeur correctement mais quelque chose a dû m'échapper. :P Je vais vérifier tout ça.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #7 le: Décembre 19, 2012, 12:52:14 pm »
Il est possible que tu doives aussi écrire l'opérateur d'affectation. Pas sûr qu'il soit utilisé par std::vector, mais de toute façon pour que ta classe soit correcte il te le faut, celui généré par le compilateur n'est pas plus correct que le constructeur par copie.
Laurent Gomila - SFML developer

Enzo76

  • Newbie
  • *
  • Messages: 5
    • Voir le profil
Re : Utiliser le constructeur par défaut d'une classe pour remplir un vector.
« Réponse #8 le: Décembre 19, 2012, 02:21:56 pm »
Ça fait une heure que je tourne mon code dans tous les sens alors qu'il suffisait de rajouter ces quelques lignes dans l'opérateur d'affectation :
        myImage=forme.myImage;
        mySprite=forme.mySprite;
        mySprite.SetImage(myImage);
J'ai encore quelques crashs parfois je ne sais pourquoi mais ça marche déjà beaucoup mieux ! ;D
Je te remercie pour ton aide très précieuse !  ;)