2010-01-27 24 views
7

Actualmente estoy intentando implementar una fábrica como singleton. Prácticamente utilicé el ejemplo del libro de texto del patrón Singleton. Aquí está el archivo .h:C++: referencia no definida a la instancia en la clase Singleton

namespace oxygen{ 

class ImpFactory{ 

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

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

y aquí está el archivo .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; 
} 

El código se compila, pero me da un error de vinculador:

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

Esto tiene actualmente tres estudiantes perplejo. ¿Algunas ideas?

Respuesta

13

Debe definir la instancia estática, no solo declararlo. La definición crea el objeto real al que se refiere.

En el archivo cpp, añada la línea:

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

Se necesita una definición para el miembro estático en un archivo CPP.

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

En su C++ añadir lo siguiente:

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

en otra nota al margen, tal vez debería hacer que la instancia puntero a un miembro estático de la función get en lugar de la clase, esto no hace demasiado mucha diferencia cuando usa el método nuevo/puntero que es. pero si solo estuvieras creando una instancia estática (es decir, sin usar un puntero y devolviéndole una referencia desde la función get get) esto hace una gran diferencia porque:

si es un miembro estático de una clase, su constructor es llamado siempre (porque es un global) si es un miembro estático de la función get, no se construye hasta que se llama la primera vez, esto alivia algunos de los problemas que la gente tiene con los singletons y que son gloriosos globales, la otra cosa buena es decir, la mayoría de los vinculadores omitirán la función get y, por lo tanto, la instancia estática por completo si nunca se llama, por lo que no tendrá que preocuparse de llamar a new para que solo utilice la memoria si se está utilizando.

0

Dado que está utilizando Boost, es posible que desee considerar las clases de singleton de Boost. Check out:

#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; 
} 

Lo que usa depende de lo que esté haciendo. Aunque soy un poco anti singleton por las razones habituales, tiene sentido reutilizar siempre que sea posible. Sin embargo, una palabra de advertencia: el singleton de Boost parece haberse movido un poco en las bibliotecas, por lo que puede variar según la versión de Boost que esté utilizando.

+0

Creo que no es tanto "movido" como "agregado cuando alguien pensó que querían un singleton, luego se lo quitaron cuando se dieron cuenta de que no era una buena idea después de todo". –

Cuestiones relacionadas