2010-01-27 4 views
7

J'essaie actuellement d'implémenter une fabrique en tant que singleton. J'ai pratiquement utilisé l'exemple du modèle Singleton. Voici le fichier .h:C++: Référence non définie à l'instance dans la classe Singleton

namespace oxygen{ 

class ImpFactory{ 

public: 
    static boost::shared_ptr<ImpFactory> GetInstance(); 

private: 
    static boost::shared_ptr<ImpFactory> mInstance; 
}; 

et voici le fichier .cpp:

#include "impfactory.h" 

using namespace oxygen; 
using namespace boost; 

shared_ptr<ImpFactory> ImpFactory::GetInstance(){ 
    if (mInstance.get() == 0) 
     mInstance = shared_ptr<ImpFactory>(new ImpFactory()); 
    return mInstance; 
} 

Le code compile, mais je reçois une erreur de liaison:

../../lib/oxygen/liboxygen.so.3.2.4: undefined reference to `oxygen::ImpFactory::mInstance'

Ce compte actuellement trois étudiants perplexe. Des idées?

Répondre

13

Vous devez définir l'instance statique, pas simplement la déclarer. La définition crée l'objet réel auquel vous faites référence.

Dans votre fichier cpp, ajoutez la ligne:

boost::shared_ptr<ImpFactory> ImpFactory::mInstance; 
2

Vous avez besoin d'une définition pour votre membre statique dans un fichier cpp.

boost::shared_ptr<ImpFactory> ImpFactory::mInstance; 
2

Dans votre C++ ajouter ceci:

boost::shared_ptr<ImpFactory> ImpFactory::mInstance; 
0

sur une autre note de côté, peut-être vous devriez faire l'instance pointeur un membre statique de la fonction get plutôt que la classe, cela ne fait pas trop beaucoup de différence lorsque vous utilisez la nouvelle méthode/pointeur que vous êtes. mais si vous créez simplement une instance statique (c'est-à-dire n'utilisez pas de pointeur et renvoyez une référence à get get), cela fait une grosse différence car:

si c'est un membre statique d'une classe, son constructeur est appelé chaque fois (parce que c'est un global) si c'est un membre statique de la fonction get, il n'est pas construit jusqu'à ce qu'on l'appelle la première fois, cela atténue certains problèmes que les gens ont avec les singletons et les globales glorifiés, l'autre bonne chose En effet, la plupart des linkers omettent la fonction get et donc l'instance statique si elle n'est jamais appelée, vous n'avez donc pas à vous soucier d'appeler new pour utiliser uniquement la mémoire si elle est utilisée.

0

Étant donné que vous utilisez Boost, vous pouvez envisager les classes Boost singleton. Extraire:

#include <boost/serialization/singleton.hpp> 

using namespace boost::serialisation; 

struct MyClass : public singleton<MyClass> 
{ string name_; int age_; }; 

int main(int argc, char* argv[]) 
{ 
    MyClass::get_mutable_instance().name_ = "Robin"; 
    MyClass::get_mutable_instance().age_ = 21; 
} 

Ce que vous utilisez dépend de ce que vous faites. Alors que je suis un peu anti-singleton pour les raisons habituelles, il est logique de réutiliser autant que possible. Un mot d'avertissement cependant: le singleton Boost semble avoir bougé un peu dans les bibliothèques, cela peut donc varier selon la version de Boost que vous utilisez.

+0

Je pense que ce n'est pas tellement "déplacé" que "ajouté quand quelqu'un pensait qu'il voulait un singleton, puis retiré quand ils ont réalisé que ce n'était pas une bonne idée après tout". –

Questions connexes