Bonjour, voici ma bouteille à la mer pour avoir de l'aide en CPP
J'apprends le C++ tout seul (donc je m'excuse d'avance si je n'utilise pas les bons termes) pour faire de la programmation de jeux avec SFML, j'ai trouvé un PDF assez bien fait mais qui part en live lors de la création d'une classe pour charger les textures.
J'ai réussi tant bien que mal à comprendre le concept de créer un espace de noms, et d'utiliser un pointeur unique, mais c'est encore un peu complexe pour moi. La particularité du PDF, c'est qu'il a l'air de tout mettre dans un fichier, là où je souhaiterai fragmenter en plusieurs fichiers (donc ça arrive que je me plante - mais je ne crois pas que ce soit le cas ici).
Du coup mon soucis:
En voulant faire la classe de chargement des textures, j'ai créé un fichier textureHolder.h avec la classe TextureHolder:
Quand j'exécute le code, j'obtiens cette erreur que je ne comprends pas trop, qui parle de fonction supprimée.
Erreur C2280 'std::pair<const Textures::ID,std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>>::pair(const std::pair<const Textures::ID,std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>> &)' : tentative de référencement d'une fonction supprimée goSfml C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xmemory 682
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xmemory(682,47): error C2280: 'std::pair<const Textures::ID,std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>>::pair(const std::pair<const Textures::ID,std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>> &)' : tentative de référencement d'une fonction supprimée
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\utility(210): message : voir la déclaration de 'std::pair<const Textures::ID,std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>>::pair'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\utility(210,5): message : 'std::pair<const Textures::ID,std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>>::pair(const std::pair<const Textures::ID,std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>> &)' : la fonction a été supprimée implicitement, car un données membres appelle une fonction supprimée ou inaccessible 'std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>::unique_ptr(const std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>> &)'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\memory(3291,5): message : 'std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>>::unique_ptr(const std::unique_ptr<sf::Texture,std::default_delete<sf::Texture>> &)' : la fonction a été supprimée explicitement
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xtree(354): message : voir la référence à l'instanciation de la fonction modèle 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,_Ty&>(_Alloc &,_Objty *const ,_Ty &)' en cours de compilation
Avec d'autres erreurs qui viennent ensuite.
En fouillant un peu, j'ai isolé la ligne qui provoquait l'erreur, qui est "std::unique_ptr", dans textureHolder.h :
Là comme ça, j'ai l'impression que mon mTextureMap n'est pas initialisé et qu'il aime pas ça, mais je trouve pas la solution. Du coup je serai content d'avoir quelques explications sur ce qui ne va pas, quelles sont les bonnes pratiques, comment je peux pratiquer les pointeurs uniques pour que je puisse maitriser un peu + le sujet Le c++ tout seul c'est pas facile ..
Je suis très novice, je saurai difficilement répondre à 'pourquoi j'ai fait ça' plutôt qu'autre chose, mais je suis à l'écoute de tout conseil !
N'importe quel sujet, tout seul, c'est pas facile quand on débute de 0.
Quel PDF ? Tu as regardé le cours C++ de Zeste de Savoir ?
enum class ID { Landscape, Airplane, Missile }; // ajoute "class". Et c'est étrange d'utiliser un enum pour un ID
auto texture { std::make_unique<sf::Texture>() };
// utilise make_unique au lieu de new. Et si tu veux, "auto"
sf::Texture& GetTexture(Textures::ID id);
// et si la texture n'existe pas ? Et pourquoi une ref non const, c'est modifiable ?
TextureHolder textures;
// Player qui est propriétaire de TextureHolder, c'est tres louche
mTextureMap.emplace(id, std::move(texture));
// utilise emplace a la place de insert
Mais pour ton erreur de compilation, c'est étrange. Ton code semble valide. Tu es sur d'avoir montré correctement ton code ? Et que l'erreur correspond bien a cette ligne de code ?
Il faut que tu montres le message d'erreur correspond a ton code, pas au code interne de Visual Studio.
L'un des soucis est que tu déclares un TextureHolder dans ton constructeur de Player, puis tu tentes de récupérer une texture chargée que tu assignes à mTextures, puis vient la fin du constructeur... et donc la fin de TextureHolder!
Donc les prochains appels à ta ressource ne se passeront pas bien, puisqu'elle sera détruite...
Tu as plusieurs solutions mais pour moi tu dois externaliser ton TextureHolder, et donner en paramètre du constructeur de Player la texture que tu veux utiliser.
Attention également, là tu copies une texture dans ton Player, et ça peut devenir très vite gourmand en ressources!
Penses donc à ne garder q'une référence vers cette texture (par exemple, Textures::ID).
Si c'est bien le livre auquel je pense (SFML Game Development), cette classe deviendra ensuite un template générique permettant de charger des Textures, mais également les autrzs ressources se basant sur le même schéma que sf::Texture.
Non je suis sûr de rien, mais ça a été à force de commenter et de remplacer les éléments de mon code pour "remonter" son exécution. Je n'ai visiblement plus d'erreurs une fois std::unique_ptr<sf::Texture>> mTextureMap, et plus particulièrement std::unique_ptr<sf::Texture> mais c'est très possible que je me trompe.
gbdivers a écrit:
Champ' a écrit:
Le c++ tout seul c'est pas facile ..
N'importe quel sujet, tout seul, c'est pas facile quand on débute de 0.
Quel PDF ? Tu as regardé le cours C++ de Zeste de Savoir ?
enum class ID { Landscape, Airplane, Missile }; // ajoute "class". Et c'est étrange d'utiliser un enum pour un ID
auto texture { std::make_unique<sf::Texture>() };
// utilise make_unique au lieu de new. Et si tu veux, "auto"
sf::Texture& GetTexture(Textures::ID id);
// et si la texture n'existe pas ? Et pourquoi une ref non const, c'est modifiable ?
TextureHolder textures;
// Player qui est propriétaire de TextureHolder, c'est tres louche
mTextureMap.emplace(id, std::move(texture));
// utilise emplace a la place de insert
Mais pour ton erreur de compilation, c'est étrange. Ton code semble valide. Tu es sur d'avoir montré correctement ton code ? Et que l'erreur correspond bien a cette ligne de code ?
Il faut que tu montres le message d'erreur correspond a ton code, pas au code interne de Visual Studio.
Je vais essayer de reprendre avec tes modifications ! J'ai montré le code qui me paraissait pertinent mais je peux mettre l'ensemble de mon projet en ligne. Mon code fonctionnait quand je faisais un chargement de texture sans classe, et a commencé à générer des erreurs après la création de la classe et des fichiers TextureHolder.
Qu'est-ce que tu entends par le message d'erreur du code ? C'est les seuls que j'ai, et visualStudio ne me souligne pas de problèmes dans mon code
Concernant les PDF, j'ai suivi 'Programmez avec le langage CPP' du site/livre du zéro, qui est un peu obsolète aujourd'hui, et 'SFML Game Developement' qu'à mentionné nours59. Je connaissais pas du tout Zeste de Savoir, je vais reprendre avec ce site. J'ai conscience que je manque de base un peu + solide et à jour mais je ne trouvais pas mieux jusqu'à présent.
Dans tous les cas je vais reprendre avec tous ces éléments et réessayer
nours59 a écrit:
Hello,
L'un des soucis est que tu déclares un TextureHolder dans ton constructeur de Player, puis tu tentes de récupérer une texture chargée que tu assignes à mTextures, puis vient la fin du constructeur... et donc la fin de TextureHolder!
Donc les prochains appels à ta ressource ne se passeront pas bien, puisqu'elle sera détruite...
Tu as plusieurs solutions mais pour moi tu dois externaliser ton TextureHolder, et donner en paramètre du constructeur de Player la texture que tu veux utiliser.
Attention également, là tu copies une texture dans ton Player, et ça peut devenir très vite gourmand en ressources!
Penses donc à ne garder q'une référence vers cette texture (par exemple, Textures::ID).
Si c'est bien le livre auquel je pense (SFML Game Development), cette classe deviendra ensuite un template générique permettant de charger des Textures, mais également les autrzs ressources se basant sur le même schéma que sf::Texture.
- Edité par nours59 il y a environ 17 heures
Par rapport au constructeur, comme tu le dis ça me fait sens.. Je l'ai mis dans le constructeur parce que, avant d'en faire une classe, mon code fonctionnait en appelant la texture sans TextureHolder.h/cpp et de cette manière (dans player.cpp) :
Comme il s'agissait de remplacer cette configuration par une classe TextureHolder, je l'ai mise dans le constructeur.
Je ne sais pas trop ce que tu entends par 'externaliser TextureHolder', mais je vais creuser dans ce sens avant de remettre à jour le poste, et reprendre avec le zestedusavoir (merci pour le lien dans ta signature d'ailleurs).
J'ai utilisé ce livre, il n'est pas parfait ni récent (au mieux, C++11), c'est l'un des plus correcte que j'ai lu jusqu'à présent.
Champ' a écrit:
Je ne sais pas trop ce que tu entends par 'externaliser TextureHolder', mais je vais creuser dans ce sens avant de remettre à jour le poste, et reprendre avec le zestedusavoir (merci pour le lien dans ta signature d'ailleurs).
Si on definit les rôles de chaque classe: TextureHolder: Un conteneur de textures où les classes représentant les différents elements graphiques pourrons "pêcher" la ou les textures qui les intéressent. Idéalement, une seule et unique instance suffit. Player: Un élément graphique (parmi tant d'autres) représentant un avatar identifiable pour le joueur.
Le problème, est que si la classe Player instancie en interne la classe TextureHolder, comment ses voisins (classe Ennemy, classe Sprite ect ...) feront-elles pour avoir accès à ce même TextureHolder sans violer la classe Player ? Clairement, cela indique qu'il n'est pas de la responsabilité de la classe Player d'instancier la classe TextureHolder (cela doit être fait ailleurs, d'où "Externaliser"). Elle peut en revanche, détenir une référence sur cette dernière. Quand à la façon d'implémenter ce comportement, je te laisse y réfléchir.
Pointeur Unique avec SFML
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Discord NaN. Mon site.
Cours de C++ moderne