1230

Ah, j'avais pas vu le static de la méthode... Donc d'après le code de ./1221, elle retourne la variable statique de l'objet (return _instance), qui est elle-même l'objet ? (static Singleton _instance)

1231

le code de getInstance() du ./1221 est incomplet: il faut vérifier si _instance est == NULL et faire quelque chose si c'est le cas.

1232

Ah ok, je me disais aussi ^^
On ne peut pas avoir une variable static bool _exist qu'on initialise à false en début de programme, puis quand on appelle getInstance, on fait ça :
if (!_exist)
{ _exist = true; _instance = new Instance();}
return _instance;

C'est le principe ?

En, fait, au lieu d'avoir des Message->sendMessage() dans mon code, je vais avoir des Message::getInstance()->sendMessage() grin
Mais je n'aurai pas de paramètre à passer dans les protos, c'est sûr. Et je peux utiliser un namespace pour alléger encore. smile



Sinon, pour mes messages, j'ai des ID d'objets associés à des pointeurs d'objets Receive, enregistrés dans un conteneur du gestionnaire de message. Ce conteneur contient donc les références nécessaires pour envoyer un message à tout objet qui s'est identifié.
Le conteneur map me parait tout à fait approprié à ça, vous en pensez quoi ? ( http://www.cplusplus.com/reference/stl/map/ )

1233

Folco (./1232) :
Ah ok, je me disais aussi ^^
On ne peut pas avoir une variable static bool _exist qu'on initialise à false en début de programme, puis quand on appelle getInstance, on fait ça :
if (!_exist)
{ _exist = true; _instance = new Instance();}
return _instance;

C'est le principe ?

c'est exactement ça. En pratique, pas besoin de _exist, il suffit d'initialiser _instance à NULL au début, et de vérifier si _instance est NULL dans getInstance().

Sinon, pour mes messages, j'ai des ID d'objets associés à des pointeurs d'objets Receive, enregistrés dans un conteneur du gestionnaire de message. Ce conteneur contient donc les références nécessaires pour envoyer un message à tout objet qui s'est identifié.
Le conteneur map me parait tout à fait approprié à ça, vous en pensez quoi ? ( http://www.cplusplus.com/reference/stl/map/ )

oui, c'est parfaitement adapté.

1234

Cool !
Seul truc un peu dommage, il faut initialiser _instance à NULL... je trouve pas ça très propre, si on oublie, crash assuré.
Or on ne peut initialiser une variable static dans une classe que si elle est aussi const, ce qui ne nous convient évidemment pas.
Il n'y aurait pas un moyen de faire plus propre ?

Genre moi je m'en fous, mais dans le cas d'une classe distribuée à un client, on fait quoi ? Voilà, je vous vends ma classe xyz€, mais n'oubliez pas de faire un _instance = NULL; avant de l'utiliser, hein ? grin

1235

header.h: class Class { static int i; }
code.c: int Class::i = 0;
Non ?
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1236

Non, tu peux pas initialiser un membre static dans la déclaration, apparemment à cause de la compilation séparée, tu te retrouverais avec plusieurs instances d'un membre static.
Ou alors, ton i doit être const.

1237

C'est pas un problème ça. Le linker C++ élimine automatiquement le code dupliqué normalement. C'est ce qui te permet d'implémenter des méthodes directement dans le .h ^^
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1238

1239

Peut-être, tu diras ça à mon bouquin, j'invente rien (même ça veut pas dire que t'as pas raison si j'ai mal lu ou que mon bouquin se plante cheeky.

1240

Euh par contre, j'ai un problème pour implémenter :
ssage; }
Ce code :Message::Message *getMessenger()
{
    if (Message::m_Message == NULL)
        Message::m_Message = new Message;
    return Message::m_Me
déclenche une erreur parce que Message est privé... C'est parce que getMessenger() est static j'imagine ? Ben... il faut bien qu'il le soit, non ?
Ma déclaration, élaguée :
class Message
{
    public:
        static Message *getMessenger();
        static Message *m_Message;
        virtual ~Message();

    private:
        Message();                              // Designed to be a singleton
        Message(const Message&);
        Message operator=(const Message&);
};

1241

./1238 > En même temps, si le C++ avait été mieux conçu à la base, il n'y aurait pas ce problème. tongue
Y'a qu'un seul moyen de remédier à la compilation séparée, c'est ne pas faire de compilation séparée…
(Et la compilation séparée est réellement un problème, au niveau de l'optimisation: Le compilateur peut pas savoir si ta fonction est inlinable sans en avoir le code.)
(PS: Heureusement MSVC++ est là pour nous… Et LLVM un jour peut-être…)

Folco > Teste le code que je t'ai mis et on en reparlera. À ma connaissance, ça marche très bien. (Si j'ai pas fait d'erreur tongue)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1242

Je comptais bien tester, mais flemme de pourrir mon arborescence avec un proje de deux lignes, donc faut d'abord que je compile ce que j'ai, donc faut que je résoudrisse mon pb de compilation au ./1240 ^^
(et ça n'a rien à voir avec l'initialisation d'un membre static)

1243

Folco (./1232) :
En, fait, au lieu d'avoir des Message->sendMessage() dans mon code, je vais avoir des Message::getInstance()->sendMessage() grin
Mais je n'aurai pas de paramètre à passer dans les protos, c'est sûr. Et je peux utiliser un namespace pour alléger encore. smile
Exactement smile Tu pourrais aussi avoir des Message::sendMessage() à la place du Message::getInstance()->sendMessage(), par exemple smile
Sinon je n’ai pas en tête les subtilités du langage C++ mais sur Wikipédia il y a plusieurs exemples d’implémentation du Singleton en C++, avec leurs avantages et inconvénients.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

1244

Bah, personnellement, je ferais un message.cpp avec des variables file-scope comme:
static QList<Message> messageQueue;
et des fonctions du genre:
void sendMessage(const Message &msg)
{
  …
}

(éventuellement dans un namespace Message; si tu veux faire super-propre, mais AMHA on s'en passe très bien) et un message.h avec les prototypes:
void sendMessage(const Message &msg);
…


Le singleton ne fait que compliquer les choses et n'a aucun intérêt ici. C'est de l'OO juste pour être OO, quand la solution procédurale est évidente et marche très bien.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

1245

Ah oui, tu me rapelles que j'avais prévu de répondre à ça:
Folco (./1202) :
Voilà. Je peux vouloir dire : "ajoute cette unité (n° tant) à cette armée" + "déduis le prix de l'unité du portefeuille du joueur" + "mets à jour la liste d'icones des unités dans le menu".
Tout ça suite à un seul clic. Le problème, c'est qu'un tel message s'adresse à plusieurs objets... : objet Module pour rajouter une icone à la liste du module, objet Joueur->Portefeuille pour le fric, objet Joueur->Armée etc...
Donc 3 messages à propager, sachant que je ne gérais pas une pile de message mais un seul message (j'ai pensé à faire une pile, mais c'est très couteux de parcourir une pile pour chaque objet, surtout que sur l'ensemble, très peu auront un message à leur intention). Et mon Message était fortement typé : transmission de deux int + 1 pointeur. Génial, mais c'est hyper limitatif.
Là, l'avantage est que je peux faire une sorte de protocole (je sais pas comment appeler ça) :
- je vais t'envoyer deux pointeurs sur des objets dont tu sais quoi faire
- ok (je prépare ma liste)
- en v'là un- et voilà, fini
Ce que tu décris devrait être géré de manière séquentielle, et non en « parallèle » avec des messages.
Typiquement, tu veux créer une unité, tu dois procéder de la sorte*: (ou très similairement)
1 - Vérifier que les ressources soient disponibles. Si oui => 2; Sinon => 5
2 - Créer l'unité et déduire les ressources « simultanément ».
3 - Ajouter l'unité.
4 - Rafraîchir l'interface utilisateur.
5 - Fin

Le système de message te servirait pour une notification de type « Unité ajoutée » à laquelle le code pourrait répondre pour l'interface utilisateur, on est d'accord. Mais pour le reste quoi, tu vas envoyer un message « Requête ajout d'unité » auquel un objet va répondre ? Puis une notification « Ajout autorisé » auquel un autre objet va répondre ?

Certains disent parfois « envoyer un message » à un objet pur « appeler une méthode » sur un objet. C'est ce qui est reflété en Objective-C par exemple (par la syntaxe et la dénomination officielle). Il me semble que c'est ce qui serait utile dans ton code, au lieu d'un système certes correct, mais complexe à mettre en place. (Complexe pas à cause du système en lui même, mais parce qu'il va rendre ton code autour plus complexe.)

Je sais pas ce que les autres en pensent, mais moi je ne vois pas pourquoi tu ne te contentes pas de bêtes appels de méthodes. Ça a été fait pour ça. tongue

* Je considère un processus mono-tache pour simplifier.
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1246

GoldenCrystal (./1235) :
header.h:class Class { static int i; }
code.c:static int Class::i = 0;
Non ?

Il ne faut pas mettre le "static" dans le .cpp

Folco (./1240) :
class Message
{
    public:
        static Message *getMessenger();
        static Message *m_Message;
        virtual ~Message();

    private:
        Message();                              // Designed to be a singleton
        Message(const Message&);
        Message operator=(const Message&);
};

m_Message ne doit surtout pas être public, sinon l'utilisateur pourrait y accéder sans passer par getMessenger().
Quand aux différent types de constructeurs et la surcharge de '=', je n'en vois pas trop l'utilité dans un singleton.
En tout cas, je ne trouve pas où est ton problème de compilation.

edit: As-tu bien mis "Message *Message::m_Message = NULL;" au début de ton Message.cpp?
edit2: Le destructeur doit être privé, tu veux pas que quelqu'un puisse faire "delete Message::getMessenger();"

1247

Jyaif (./1246) :
Il ne faut pas mettre le "static" dans le .cpp
Ah, j'avais un doute là dessus en écrivant, je vais corriger, merci. ^^
(En plus quand on y réfléchit c logique… En dehors d'une classe, static veut dire variable non exportée… Shame on me -_-)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1248

Jyaif (./1246) :
Quand aux différent types de constructeurs et la surcharge de '=', je n'en vois pas trop l'utilité dans un singleton.

Ça évite que quelqu'un recopie l'objet.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

1249

Merci beaucoup à vous pour tous vos conseils. Hé oui, j'ai fait des erreurs débiles encode une fois. Je débute. grin

1250

Folco (./1234) :
Seul truc un peu dommage, il faut initialiser _instance à NULL... je trouve pas ça très propre, si on oublie, crash assuré.

La solution est propre en fait, c'est juste que comme d'habitude en C++ c'est pas joli et il faut faire un peu plus attention à ce que tu fais.
(Je veux dire par là qu'on ne peut pas initialiser les variables membres directement et la notation Classe::getInstance().truc est dégueu, mais c'est spécifique au C++)
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

1251

EDIT : dsl, j'ai raté une page cheeky
Un membre statique d'une classe n'est pas relié à un objet particulier, il est relié à la classe (pas à son instance).

1252

Non mais le fait de ne pas pouvoir écrire: class Pwet { static int membre = NULL; int autreMembre = 0; };
Dans un langage qui ne garantit même pas l'initialisation des membres à zéro, c'est quand même vachement handicapant et prône aux erreurs comme l'a dit Folco (enfin pour les variables statiques à la limite ça va puisqu'il faut les déclarer dans le .cpp donc on peut les initialiser à ce moment là).
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

1253

(en fait pour ./1251 j'ai raté une page cheeky)

1254

J'ai aps réussi à utiliser l'opérateur [] du conteneur map... ( http://www.cplusplus.com/reference/stl/map/operator%5B%5D/ )

J'ai utilisé find() à la place, avec succès :
void Message::sendMessage(int ID)
{
    m_EntriesList->find(ID)->second->receive();
}


Mais à la base, je voulais écrire quelque chose du genre :
void Message::sendMessage(int ID)
{
    *m_EntriesList[ID]->receive();
}

avec:
    std::map<int, Receive*> *m_EntriesList;
et:
    m_EntriesList = new std::map<int, Receive*>;

Mais cette "solution" ne compilait pas,je ne sais pas trop pourquoi...
Sinon, j'arrive à faire les autres manipulations d'insertion et d'effacement dans le conteneur. smile

1255

Kevin Kofler (./1248) :
Jyaif (./1246) :
Quand aux différent types de constructeurs et la surcharge de '=', je n'en vois pas trop l'utilité dans un singleton.
Ça évite que quelqu'un recopie l'objet.


Pour moi, dans pas mal de langages, en particulier ceux où on permet la copie implicite, le singleton est bon sur le principe mais pas dans son concept exact d'un objet unique/pointeur unique. Je vois deux solutions propres : par délégation, on a accès à un objet alloué qui délègue à un objet unique (pour etre clair : interface A, implantation réelle B : A qui fait les traitement et encapsule les données, et classe visible C : A, qui accède à l'unique instance de B et lui délègue ses traitements, et qui peut le cas échéant être alloué plusieurs fois, copié...). Mais je pense que le mieux, c'est comme propose Kevin, d'utiliser la partie procédurale du langage quand on traite de problèmes procéduraux.

./1245 Les deux se défendent. Un problème c'est le bruit pour pouvoir annuler un traitement en encodant la programmation réactive/évènementielle dans du passage de messages comme ça, il va falloir un signal "envoyer du bois", dans un slot "recevoir du bois", et à l'inverse un signal "bois reçu" dans un slot "valider réception bois" mais aussi un signal "bois reçu mais tout pourri" dans un slot "réessayer envoi bois", etc... (j'ai employé la terminologie Qt parce qu'elle est plus facile à écrire et comprendre je trouve mais je parle en général). D'un autre côté, pour encoder des opérations asynchrones (qui prennent du temps, qui ont besoin que d'autres choses se produisent avant de se terminer, etc.) c'est bien plus pratique.
Et puis tu es obligé d'envoyer ton signal en fin de méthode, et attendre sa réception dans une autre méthode, donc en plus tout ton état doit être dans des variables membres plutôt que locales ce qui ne fait que compliquer la vérification. Dans d'autres langages (dits réactifs) tu pourrais faire "answer = send message(args)", et le compilo se charge de découper ton code tout seul, gérer les envois de messages, etc.
Du coup effectivement, il faut je pense bien réfléchir aux parties que tu fais par passage de messages, et aux parties que tu fais par appel de méthodes, mais ce n'est pas impossible que certaines parties du jeu lui-même soient intéressantes à faire en passage de messages.
avatar
fabetal_ > Hier, je me suis fait monter par un pote
redangel > et en chevals, ça donne quoi?
Nil> OMG I think I'm gay

1256

Kevin Kofler (./1248) :
Ça évite que quelqu'un recopie l'objet.

Ca évite aussi que g++ me gueule dessus à partir du moment où j'ai un membre pointeur dans une classe. Ou je dois réimplémenter la méthodes de recopie et l'opération d'affectation, ou alors je dois les déclarer en private. C'est peut-être dû au fait que j'ai activé tous les warnings, mais je trouve ça pas con sur le principe. Une recopie qui passe inaperçue, et plouf on se retrouve avec une libération silencieuse.


Bookledor -> Oui, j'ai bien vu que ça allait changer radicalement ma façon de coder par rapport à la "boite au lettre" que j'utilisais avant et que chacun consultait en son temps. Mais j'ai pas l'expérience pour savoir ce que ça va donner dans mon code. Donc comme pour le post de Golden, je suis un peu dubitatif et perplexe, je sais pas ce que ça va donner au final. grin

1257

je ne ferai jamais de C++ sérieux. C'est abominable cette différence entre les objets sur la pile et les pointeurs sur les objets, ça apporte plein de pbms avec les constructeurs de copie et tout ça #trisick#
quel bordel pour un simple singleton! Comment accéder de manière propre a l'instance autrement que par un pointeur? chaque fois que tu déclares un objet faut recopier toutes les données de l'instance unique dans ton truc déclaré?

sans parler des surcharges d'opérateur vicieuses style appel de méthode et indice de tableaux, qui peuvent te faire prendre des vessies pour des lanternes sick

1258

L'avantage de la surcharge, c'est précisément de pouvoir utiliser des [] et -> sans que tu te préocupes de ce qu'il y a derrière tongue
Ceci dit, ça doit évidemment être utilisé à bon escient...

1259

moi ça me hérisse de penser qu'un a->b peut renvoyer (a+42*b)%69 sick

1260

Il peut pas, le type de retour de l'opérateur "->" est imposé. Et même s'il ne l'était pas, un programmeur C++ ne s'amuserait pas à coder ce genre de comportement, tout le monde sait bien que c'est stupide et il n'y a pas besoin d'utiliser un langage blindé de garde-fous pour apprendre à coder proprement.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)