Das Thema Singleton sollte ja geklärt sein. Zu static möchte ich noch kurz was ergänzen. Mal eine Beispielklasse:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
|
class Auto
{
private:
int ps;
public:
void Fahren();
};
|
Was in der Funktion passiert soll hier nicht unbedingt wichtig sein. Wichtig ist, jede Instanz dieser Klasse hat eine eigene Version der Variable "ps" und wenn du die Funktion "Fahren" aufrufst, so tust du das auf dieser Instanz.
|
C-/C++-Quelltext
|
1
2
|
Auto auto;
auto.Fahren(); // Hier rufst du die Funktion Fahren der Klasse Auto auf der speziellen Instanz "auto" auf.
|
Static ist jetzt dafür da, um Variablen und Funktionen an die Klasse zu binden und nicht an die Instanz. Hört sich erst mal kompliziert an aber mal ein Beispiel:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
|
#include <iostream>
class Useless
{
public:
static int counter = 0;
Useless()
{
std::cout << counter << std::endl;
counter++;
}
};
|
Hier ist eine Klasse mit einer Variable, welche static ist. Nun gucken wir doch mal was passiert wenn wir eine Instanz davon anlegen:
|
C-/C++-Quelltext
|
1
|
Useless u;
|
Hier die Ausgabe:
|
Quellcode
|
1
|
0
|
Nicht sonderlich überraschen, ich weiß. Dafür hätten wir jetzt kein static gebraucht. Gucken wir mal was passiert wenn wir mehrere Instanzen anlegen:
|
C-/C++-Quelltext
|
1
2
3
4
|
Useless u1;
Useless u2;
Useless u3;
Useless u4;
|
Ausgabe:
|
Quellcode
|
1
2
3
4
|
0
1
2
3
|
Hmm das sieht schon anders aus. Da stellt sich jetzt die Frage warum das so ist. Wie oben schon geschrieben, koppelt static die Variable oder Funktion an die Klasse und nicht an eine Instanz. Noch mal zur Auffrischung, die Klasse ist in diesem Fall "Useless" und die Instanzen sind im oberen Fall "u" und im unteren "u1", "u2", "u3", "u4". Im unteren Fall wird der Konstruktor von "u1" aufgerufen. Die statische Variable "counter" wurde mit 0 initialisiert. Im Konstruktor wird sie nun ausgegeben und dann um 1 erhöht. Jetzt wird der Konstruktor von "u2" aufgerufen. Da die Variable zur Klasse und nicht zur Instanz gehört hat sie auch hier den Wert 1 und nicht wie du vielleicht erwarten würdest 0. Es wird also eine 1 ausgegeben und die Variable danach wieder um 1 erhöht. Sie hat jetzt den Wert 2. Diesen Wert hat sie in der Instanz "u1" und in der Instanz "u2" da die Variable ja wie gesagt unabhängig von den Instanzen ist. Du fragst dich hier vielleicht warum man das ganze braucht. Das ist erst mal unwichtig. Am Anfang braucht man das meiner Erfahrung nach eigentlich gar nicht. Ein Anwendungsbeispiel ist wie du ja gesehen hast das Singleton. Hinterher wirst du sicherlich mal über Smartpointer stoßen. Die benutzen (zumindest soweit ich weiß) statische Variablen als Referenzzähler. Das sagt dir jetzt erst mal nichts, ist aber auch nicht unbedingt wichtig.
Wichtig ist aber, wenn du statische Funktionen benutzt, so darfst du in diesen Funktionen nur auf statische Variablen zugreifen. Hört sich erst mal komisch an, aber wenn man kurz drüber nachdenkt merkt man schnell warum das so ist. Statische Funktionen sind Klassenbezogen und nicht Instanzbezogen. Mal ein Beispiel:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
|
#include <iostream>
class TestKlasse
{
private:
int wert = 0;
public:
static void MachWas()
{
std::cout << wert << std::endl; // Hier ist ein Fehler
}
};
|
Die statische Funktion "MachWas" soll die Variable "wert" ausgeben. Da die Variable aber nicht statisch ist, ist sie fest mit einer Instanz verbunden. In jeder Instanz der Klasse "TestKlasse" kann die Variable einen anderen Wert haben. Würde man jetzt die statische Funktion "MachWas" aufrufen, so wüsste diese nicht welche Variable "wert" sie nun ausgeben soll. Möglicherweise gibt es 5 verschiedene Instanzen bei denen die Variable verschiedene Werte besitzt. Ändert man das ganze jetzt ab und macht die Variable statisch sieht es folgendermaßen aus:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
|
#include <iostream>
class TestKlasse
{
private:
static int wert = 0:
public:
static void MachWas()
{
std::cout << wert << std::endl; // Hier ist kein Fehler mehr.
}
};
|
Schon funktioniert das ganze. Wenn es etwas verwirrend ist, ist das nicht ungewöhnlich. Mit der Zeit wirst du verstehen wofür du das gebrauchen kannst.
Was das Schachspiel angeht, im Buch werde die Techniken erklärt die du grundlegend brauchst. Ich schlage dir vor dich erst mal mit einfacheren Dingen als Schach zu beschäftigen. Technisch weißt du was zu tun ist, wirst deine Ideen direkt nach dem Buch aber vermutlich noch nicht umsetzen können. Das was dabei fehlt wird dir auch kein Buch beibringen können. Da fehlt einfach Erfahrung. Du kannst dich natürlich auch direkt an ein Schachspiel begeben, das Ding wird dann aber vermutlich nicht fertig werden. Damit will ich dich nicht demotivieren. Das ist normal und eigentlich gar nicht so schlimm. Arbeite erst mal weiter das Buch durch und guck dann noch mal. Bis dahin hast du vielleicht andere Dinge die du umsetzen möchtest. Und wenn du es dann doch direkt mit Schach versuchen möchtest, wer weiß, vielleicht ist dir ja direkt klar wie du das ganze angehen musst. Aber das sollte jetzt erst mal nicht wichtig sein. Erst mal gilt es das Buch weiter durchzuarbeiten