2009-09-07 13 views
8

Cheers,Singletons tramite istanza statica in C++ - in origine o in file di intestazione?

mi sono imbattuto in questo pezzo di codice in "Programmazione Gioco AI by Example":

/* ------------------ 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; 
} 

Sono confuso dalla dichiarazione dato di fatto da parte dell'autore che la variabile dichiarata staticamente all'interno di una funzione nell'intestazione risulterebbe la dichiarazione di più variabili statiche separate instance. Non penso di aver visto questo comportamento nelle mie abituali implementazioni della funzione getInstance() che inserisco regolarmente nelle intestazioni (ad eccezione del fatto che mi piace giocare con i puntatori e inizializzare il singleton al primo utilizzo). Sto usando GCC per il mio lavoro.

Quindi cosa dice lo standard? Cosa dicono i compilatori non conformi? La dichiarazione dell'autore è corretta e, in caso affermativo, puoi nominare alcuni compilatori che creerebbero più istanze se getInstance() fosse dichiarato nelle intestazioni?

+4

Una grande discussione su come realizzare un singoletto, insieme con filo di sicurezza in C++ possono essere trovate in questo documento: http://www.aristeia.com/Papers/DDJ%5FJul%5FAug%5F2004%5Frevised .pdf –

risposta

10

In C++ nulla impedisce ad una funzione inline di avere una variabile statica e il compilatore deve arrangiarsi per rendere tale variabile comune tra tutte le unità di traduzione (come deve fare per i membri della classe statica di istanze template e le variabili di funzione statiche). 7.1.2/4

Una variabile static in funzione extern inline riferiscono sempre allo stesso oggetto.

Si noti che in C, le funzioni in linea non possono avere variabili statiche (né fare riferimento a oggetti con collegamento interno).

+0

In altre parole, una "variabile statica" definita in una "funzione statica inline" in myclass.h verrà visualizzata una sola volta nel codice collegato risultante e verrà condivisa tra i file di origine (come main.cpp, myclass.cpp e joetheplumber.cpp)? Spostare :: Instance() dal codice sopra nell'intestazione garantirà comunque che la stessa istanza venga restituita a diversi file .cpp? –

+0

Fintanto che il compilatore è conforme.Dato che non ricordo alcun problema e l'instabilità è necessaria per il modello, non ho paura su questo punto. – AProgrammer

+1

Non ho sentito parlare dei recenti problemi con questo, né in VC6 o GCC 2.95. – MSalters

1

Ho provato il codice che l'OP ha pubblicato con VS2008 in quattro modi e non sembra esserci un problema con l'istanza statica di MyClass all'interno di MyClass::Instance().

  1. Instance() è definito in MyClass.cpp: Questo è il modo normale tutto va bene.
  2. Instance() è definito solo all'interno della dichiarazione della classe . Questa è l'alternativa e tutto è a posto.
  3. Instance() è definito inline fuori dalla classe, ma nell'intestazione e tutto è a posto.
  4. come 3. ma senza la inline e il linker dice che ci sono definizioni mutiple di Instance()

Penso che l'autore del libro si occupa 4. sopra e sa che l'istanza statica di MyClass sarà curato in un programma che compila e collega.

+0

Ti segnerei come accettato, ma l'ho già fatto con AProgrammer e mi sentirò molto male a cambiare il segno di spunta. Quindi, ecco solo un upvote per un ragionamento molto chiaro. –

Problemi correlati