2012-06-04 36 views
6

Ich versuche, eine Data Klasse zu erstellen, deren Objekte jeweils eine eindeutige ID enthalten.Statischer Zähler in C++

möchte ich die ID des ersten Objekts 1 sein, die zweite 2 sein, usw. ich ein static int verwenden müssen, aber alle die Objekte die gleiche ID haben, nicht mehr als 1, 2, 3 ...

Dies ist die Data Klasse:

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

Wie kann ich es so die erste ID tun 1 wäre, würde der zweite 2 usw. sein ..?

+0

Stellen Sie sicher, dass Sie t Achten Sie auf Multithreading, da die Variable "statisch" ist. – iammilind

+0

Im Allgemeinen benutzen die Leute 'long' für diese eher als' int'. – shan

+0

@shan: Welche Leute? Es kann sein, was immer er will. –

Antwort

9

Wenn die ID statisch ist, hat sie für alle Klasseninstanzen denselben Wert.

Wenn Sie jede Instanz wollen sequenzielle ID-Werte haben, dann könnten Sie das statische Attribut mit einer Klassenvariablen kombinieren, wie folgt aus:

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

int Data::ID = 0; 

Wenn die Anwendung multi-threaded sein wird, dann werden Sie um es mit etwas wie einem Pthread-Mutex zu synchronisieren.

+0

danke, dachte über diese Lösung nach, aber ich frage mich, ob es eine andere Möglichkeit gibt, es zu tun, nur mit dem statischen Int, da ich aufgefordert wurde, es nur mit statischen Int zu tun. Vielen Dank! :) – Jjang

+0

@Jjang, Sie könnten es mit nur einem statischen int tun, wenn Sie nur den Wert im Konstruktor drucken, aber wenn Sie *** den eindeutigen sequentiellen Wert *** speichern müssen, dann brauchen Sie mehr als nur das statische int. – Brady

+0

@Jjang: Sie können nicht * eindeutige * IDs pro Objekt mit einer einzigen * shared * ID ('statisch') haben, das macht überhaupt keinen Sinn. –

14

Dieses:

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

Neben einem statischen Zähler, müssen Sie auch eine Instanz gebundenes Mitglied.

+3

Die Mitglieds-ID sollte ein "const" -Feld sein. Sobald das Objekt erstellt ist, macht es wahrscheinlich wenig Sinn, es zu ändern. Es verhindert auch automatisch, dass "operator =" die ID des Objekts überschreibt, obwohl der Benutzer die Verantwortung hat, einen Kopierkonstruktor zur Verfügung zu stellen, der die ID des Quellobjekts nicht wiederverwenden kann. –

+0

@ DavidRodríguez-Dribeas guten Punkt. –

+0

Ich traf einen Fehler mit 'const' vielleicht aufgrund meines von Benutzern deklarierten Konstruktors. Siehe [diese Antwort] (http://stackoverflow.com/a/37517125/5272567). Entferne 'const' "fixed" dies bedeutet natürlich, dass die Variable nicht 'const' ist. – Matthias

1

Jede Instanz von Data benötigt eine eigene nicht statische Elementvariable, die ihre ID speichert. Eine static Variable kann verwendet werden, um die zuletzt verwendete ID zu speichern, die im Konstruktor Data inkrementiert würde.

Anstelle eines static Zähler, der nicht Thread-sicher ist, sollten boost's uuid verwendet:

#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

wo die Instanz (nicht statisch) id hier? Sie benötigen ein neues Instanz-ID-Feld wie diese

int m_ID; 

dann in Ihrem Konstruktor

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

in eine interlocked oder anderen Thread-sichere Weise

+0

Schöne Idee, aber wie tragbar ist das? – Brady

+1

Natürlich nicht portierbar ;-) Ich gab nur ein Beispiel. – Bond

1

Initialisierung der statischen Variablen innerhalb einer Funktion zu tun erklären ist erlaubt so eine Lösung kann so etwas sein

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

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