2012-06-04 16 views
6

Sto provando a creare una classe Data i cui oggetti contengono ciascuno un ID univoco.contatore statico in C++

voglio ID 1 ° dell'oggetto per essere 1, il 2 ° per essere 2, ecc devo usare un static int, ma tutti gli oggetti hanno lo stesso ID, non 1, 2, 3 ...

Questa è la classe Data:

class Data 
{ 
private: 
    static int ID; 
public: 
    Data(){ 
    ID++; 
    } 
}; 

Come posso fare in modo che il primo ID sarebbe 1, il secondo sarebbe 2, ecc ..?

+0

Assicurarsi di non prenditi cura del multithreading, dato che la variabile è 'static'. – iammilind

+0

Generalmente le persone usano 'long' per questo piuttosto che' int'. – shan

+0

@shan: Quali persone? Può essere qualunque cosa voglia. –

risposta

9

Se l'ID è statico, avrà lo stesso valore per tutte le istanze di classe.

Se si desidera che ogni istanza di avere valori ID sequenziali, allora si potrebbe combinare l'attributo statico con una variabile di classe, in questo modo:

class Data 
{ 
private: 
    static int ID; 
    int thisId; 
public: 
    Data(){ 
    thisId = ++ID; 
    } 
}; 

int Data::ID = 0; 

Se l'applicazione sarà multi-threaded, allora si dovrà per sincronizzarlo con qualcosa come un mutex pthread.

+0

grazie, ho pensato a questa soluzione, ma mi chiedevo se ci fosse un altro modo per farlo, solo con l'int statico, poiché mi è stato richiesto di farlo usando solo int statico. Grazie! :) – Jjang

+0

@Jjang, potresti farlo con un solo int statico se stampi il valore nel costruttore, ma se hai bisogno di *** memorizzare *** il valore sequenziale unico, allora avrai bisogno di più di un semplice l'int statico. – Brady

+0

@Jjang: Non è possibile avere * id * per oggetto con un singolo * shared * id ('static'), che non ha alcun senso. –

14

questo:

class Data 
{ 
private: 
    static int ID; 
    const int currentID; 
public: 
    Data() : currentID(ID++){ 
    } 
}; 

Oltre ad un contatore statico, è anche bisogno di un membro di istanza-bound.

+3

L'id membro dovrebbe essere un campo 'const'. Una volta creato l'oggetto, probabilmente non ha molto senso modificarlo. Inoltre inibirà automaticamente 'operator =' dal sovrascrivere l'id dell'oggetto, anche se l'utente ha la responsabilità di fornire un costruttore di copia che non riutilizzi l'id dell'oggetto sorgente. –

+0

@ DavidRodríguez-dribeas buon punto. –

+0

Ho riscontrato qualche errore usando 'const', forse a causa del mio costruttore di copie dichiarato dall'utente. Vedi [questa risposta] (http://stackoverflow.com/a/37517125/5272567). Rimuovendo 'const'" fixed "questo, ovviamente significa che la variabile non è' const'. – Matthias

1

Ogni istanza di Data richiede la propria variabile membro non statica che memorizza il proprio ID. Una variabile static può essere utilizzata per memorizzare l'ultimo ID utilizzato che sarebbe stato incrementato nel costruttore di Data.

Invece di un contatore static, che non è thread-safe, è consigliabile utilizzare boost's uuid:

#include <boost/lexical_cast.hpp> 
#include <boost/uuid/uuid.hpp> 
#include <boost/uuid/uuid_generators.hpp> 
#include <boost/uuid/uuid_io.hpp> 

using boost::lexical_cast; 
using boost::uuids::uuid; 
using boost::uuids::random_generator; 

std::string id_ = lexical_cast<std::string>((random_generator())()); 
-1

dove è l'istanza (non statico) id qui? è necessario dichiarare un nuovo campo ID istanza come questo

int m_ID; 

poi nel costruttore fare

Data(){m_ID = ::InterlockedIncrement(&ID);} 

in modo thread-safe interlocked o altro

+0

Bella idea, ma quanto è portatile? – Brady

+1

Non portatile a tutti ovviamente ;-) Stavo solo dando un esempio. – Bond

1

inizializzazione della variabile statica all'interno di una funzione è consentito quindi una soluzione può essere qualcosa di simile

class Data 
{ 
    private: 
    static int ID() 
    { 
     static int ID = 0; 
     return ID ++; 
    } 
    int myId; 

    public: 
    Data(): myId (ID()) 
    {  
    } 
};