2010-06-05 7 views
1

c'est ma première question sur le débordement de la pile, alors soyez doux. Permettez-moi d'abord d'expliquer le comportement exact que je voudrais voir. Si vous êtes familier avec C#, vous savez que déclarer une variable comme "readonly" permet à un programmeur d'assigner une valeur à cette variable exactement une fois. D'autres tentatives de modification de la variable entraîneront une erreur. Ce que je suis en train de faire: Je veux m'assurer que toutes les classes d'une tonne que je définis peuvent être instanciées de manière prévisible exactement une fois dans mon programme (plus de détails en bas).Atteindre C# "readonly" comportement en C++

Mon approche de la réalisation de mon objectif est d'utiliser extern de déclarer une référence mondiale à la seule tonne (que je plus tard instancier à un moment que je choisis. Ce que je ressemble un peu comme cela,

namespace Global 
{ 
    extern Singleton& mainInstance; // not defined yet, but it will be later! 
} 

int main() 
{ 
    // now that the program has started, go ahead and create the singleton object 
    Singleton& Global::mainInstance = Singleton::GetInstance(); // invalid use of qualified name 
    Global::mainInstance = Singleton::GetInstance(); // doesn't work either :( 
} 

class Singleton 
{ 
    /* Some details ommited */ 

    public: 
     Singleton& GetInstance() 
     { 
      static Singleton instance; // exists once for the whole program 
      return instance; 
     } 
} 

Toutefois, cela ne fonctionne pas vraiment, et je ne sais pas où aller d'ici

Quelques détails sur ce que je suis contre.

Je suis préoccupé par le filetage que je travaille code qui traitera de la logique du jeu pendant que communiquant avec plusieurs processus tiers et d'autres processus que je vais créer. Finalement, j'aurais pour implémenter une sorte de synchronisation afin que plusieurs threads puissent accéder aux informations dans la classe Singleton sans souci. Parce que je ne sais pas quels types d'optimisations je pourrais faire, ou exactement ce que le filetage implique (jamais fait un vrai projet en l'utilisant), je pensais que pouvoir contrôler de manière prévisible quand Singletons étaient instanciées serait un bon Chose. Imaginez si le processus A crée le processus B, où B contient plusieurs singletons répartis sur plusieurs fichiers et/ou bibliothèques. Cela pourrait être un vrai cauchemar si je ne peux pas assurer de façon fiable l'ordre dans lequel ces objets singleton sont instanciés (parce qu'ils peuvent dépendre l'un de l'autre, et appeler des méthodes sur un objet NULL est généralement une mauvaise chose).

Si j'étais en C#, j'utiliserais simplement le mot-clé readonly, mais est-il possible de mettre en œuvre ce comportement (compilé) en C++? Est-ce même une bonne idée? Merci pour vos commentaires.


Modifier

Si je fermai pour suivre l'exemple de code ci-dessus, la réponse choisie serait la meilleure façon de faire ce que je avais besoin. J'ai décidé de changer le modèle de singleton, même si je prévois de faire un de ces objets EntryPoint.

class EntryPoint 
{ 

    /* Intentionally defined this way to discourage creation */ 
    EntryPoint(const EntryPoint &); // undefined & private 
    EntryPoint& operator=(const EntryPoint &); // undefined & private 

    // public 
    EntryPoint() 
    { 
     /* All of the action is performed here! */ 
    } 

    /* Other supporting functions */ 
} 

// The easier to understand main function! 
int main() 
{ 
    EntryPoint * ep = new EntryPoint(); // transfer control to the entrypoint 
    delete ep; 
} 

L'une des raisons pour lesquelles je pensais que je aurais besoin de tous ces singletons est que je prévois de créer une architecture plus large qui soutiendrait les applications plug-in de type modulaire. Je voulais également plus de vérification des erreurs et de protection de la mémoire pour minimiser les fuites de mémoire. J'ai été heureux de constater que le Qt multiplateforme (http://qt.nokia.com/) offre un pointeur gardé et d'autres fonctionnalités intéressantes.

+3

Il semble que 'const' devrait faire l'affaire. Mais non, je ne pense pas que ce soit une bonne idée. Les singletons sont assez mauvais dans leur incarnation "normale". Les rendre encore plus complexes ne fera que revenir et vous mordre. Pourquoi avez-vous tous ces singletons de toute façon? Le moyen le plus simple de contrôler l'ordre d'instanciation est d'arrêter de faire la moitié de vos variables static/globals/singletons – jalf

Répondre

1

Pourquoi ne pas simplement utiliser Singleton::GetInstance directement? Pourquoi avez-vous besoin de le stocker dans un (en lecture seule) global? Cela résout également les problèmes de dépendance.

+0

+1 Voici comment j'appellerais la méthode Singleton GetInstance. –

+0

La moitié de moi veut savoir si c'est possible. Mais ce que j'essaie de faire est de séparer l'instanciation de l'accès. Mon sentiment est qu'un jour, je peux créer une classe AccessManager qui serait responsable de l'accélération de l'accès aux données globales (ce qui peut nécessiter d'interroger une base de données, qui sait) en utilisant des techniques de cache ou quelque chose de plus compliqué. En ce moment ce n'est pas si grave car c'est simple, mais je ne veux pas être dans une situation où il devient difficile d'optimiser car j'ai beaucoup d'appels à Singleton :: GetInstance() tout au long du code. –

+0

Pouvez-vous créer une classe (ou plusieurs classes) avec des méthodes statiques telles que 'GetGraphicsEngine' et' GetInputEngine' qui, pour l'instant, appellent 'Singleton :: GetInstance'? – strager

1

Autoriser uniquement l'accès en appelant:

Singleton::GetInstance 

Imposer cela en faisant votre copie et d'affectation des constructeurs privés

private: 
    Singleton(){} 
    Singleton(Singleton const&){}; //copy ctor private 
    Singleton& operator=(Singleton const&){}; 
+0

et Singleton :: GetInstance est statique – Joshua

0

Imaginer si le processus a crée procédé B, où B contient plusieurs singletons

De quoi pensez-vous exactement que vous ayez besoin? Singletons pour? Connaissez-vous le Anti Singleton Movement? ;-)

+0

Amusant video :) –

+0

@Matt: Par "amuser", voulez-vous dire "intéressant" ou "ridicule"? – fredoverflow

+0

Un peu des deux je suppose :) Je n'ai vu que les 10 premières minutes, et même si je suis d'accord que l'état global doit être évité (ne savons-nous pas tout?), Je sais aussi par expérience qu'il existe: ça s'appelle monde extérieur (bases de données, autres applications, ...). Je suis content pour le lien néanmoins. Et félicitations pour avoir réalisé 4k :) –

Questions connexes