2009-09-07 7 views
8

Saludos,Singletons a través de una instancia estática en C++: en archivos de origen o en archivos de encabezado?

me encontré con este trozo de código en "programación de juegos AI por ejemplo":

/* ------------------ MyClass.h -------------------- */ 
#ifndef MY_SINGLETON 
#define MY_SINGLETON 

class MyClass 
{ 
private: 

    // member data 
    int m_iNum; 

    //constructor is private 
    MyClass(){} 

    //copy ctor and assignment should be private 
    MyClass(const MyClass &); 
    MyClass& operator=(const MyClass &); 

public: 

    //strictly speaking, the destructor of a singleton should be private but some 
    //compilers have problems with this so I've left them as public in all the 
    //examples in this book 
    ~MyClass(); 

    //methods 
    int GetVal()const{return m_iNum;} 
    static MyClass* Instance(); 
}; 

#endif 

/* -------------------- MyClass.cpp ------------------- */ 

//this must reside in the cpp file; otherwise, an instance will be created 
//for every file in which the header is included 
MyClass* MyClass::Instance() 
{ 
    static MyClass instance; 

    return &instance; 
} 

Estoy confundido por el estado de la materia-de-hecho por el autor que la variable estática declarada dentro de una función en el encabezado resultaría en declarar múltiples variables estáticas separadas instance. No creo haber visto este comportamiento en mis implementaciones habituales de la función getInstance() que pongo regularmente en los encabezados (excepto que me gusta jugar con punteros e inicializar el singleton al primer uso). Estoy usando GCC para mi trabajo.

¿Qué dice la norma? ¿Qué dicen los compiladores no conformes? ¿Es correcta la afirmación del autor y, de ser así, puede nombrar algunos compiladores que crearían varias instancias si se declarara getInstance() en los encabezados?

+4

Una gran discusión sobre cómo implementar un singleton, junto con la seguridad de subprocesos en C++ se puede encontrar en este documento: http://www.aristeia.com/Papers/DDJ%5FJul%5FAug%5F2004%5Frevised .pdf –

Respuesta

10

En C++ nada impide que una función en línea tenga una variable estática y el compilador tiene que organizar esa variable entre todas las unidades de traducción (como debe hacerlo para miembros de clase estática y variables de función estáticas). 7.1.2/4

A static variable en una función extern inline siempre se refieren al mismo objeto.

Tenga en cuenta que en C, las funciones en línea no pueden tener variables estáticas (ni referencia al objeto con enlace interno).

+0

En otras palabras, una 'variable estática' definida en una 'función en línea estática' en myclass.h aparecerá solo una vez en el código vinculado resultante, y se compartirá entre los archivos fuente (como main.cpp, myclass.cpp y joetheplumber.cpp)? Mover :: Instance() del código anterior al encabezado aún garantizará que se devuelva la misma instancia a diferentes archivos .cpp. –

+0

Siempre que el compilador se ajuste.Como no recuerdo ningún problema y la plantilla es necesaria para la plantilla, no tengo miedo en ese punto. – AProgrammer

+1

No he oído hablar de problemas recientes con esto, ni en VC6 o GCC 2.95. – MSalters

1

He intentado el código que el OP publicó con VS2008 de cuatro maneras y no parece haber un problema con la instancia estática de MyClass dentro de MyClass::Instance().

  1. Instance() se define en MyClass.cpp: Esta es la forma normal todo está bien.
  2. Instance() se define solo dentro de la declaración de clase . Esta es la alternativa y todo está bien.
  3. se define inline fuera de la clase, pero en el encabezado y todo está bien.
  4. como 3. pero sin la inline y el enlazador dice que hay definiciones mutiple de Instance()

Creo que el autor del libro tiene que ver con el punto 4 anterior y sabe que la instancia estática de MiClase será cuidado en un programa que compila y enlaza.

+0

Te marcaría como aceptado, pero ya lo hice con AProgrammer y me sentiría muy mal por cambiar el tic. Así que aquí solo hay un voto positivo para un razonamiento muy claro. –

Cuestiones relacionadas