C++ Was bedeutet das Klasse::Funktion? Singleton klasse..

Abcd12345

Lt. Junior Grade
Registriert
März 2006
Beiträge
483
Hallo,

Ich bin grade in einer Dokumentation auf etwas gestossen, was ich nicht so ganz verstehe. Es geht um Singleton Klassen.

Was Singleton sind weis ich noch so ungefähr. Ich denke die Klasse erbt von einer Singletonklasse in der es eine Funktion gibt die eine Instanz von der aufrufenden Klasse erstellt, so das man die Klasse verwenden kann ohne diese Initaliesieren zu müssen.
Ist das so richtig?

In der Dokumentation gibt es eine Klasse die sich World nennt. Und diese wird immer so aufgerufen:

World::Initalize();
World::StartGame();

Ich verstehe jetzt nicht so ganz, was die Doppelpunkte zu bedeuten haben. Verbirgt sich vieleicht hinter diesen Doppelpunkten ein Funktionsaufruf der Singleton Funktion zur Instanzerstellung?
 
Ich muss zugeben, nicht ganz nachvollziehen zu können, was du meinst.
Diese Doppelpunkte dienen einfach dazu, um auf Member der Klasse (hier auf Funktionen im Gültigkeitsbereich der Klasse) zuzugreifen.
Ich denke die Klasse erbt von einer Singletonklasse in der es eine Funktion gibt die eine Instanz von der aufrufenden Klasse erstellt
Hier ist folgender Grundsatz wichtig: Die Konstruktoren der abgeleiteten Klassen initialisieren alle Basisklassen. Du kannst hier etwas an deine Konstruktoren einer Basisklasse übergeben. Tust du das nicht explizit, so wird implizit der Standardkonstruktor der Basisklasse aufgerufen.

Ein Beispiel:

MyClass::MyClass(int val, bool val2) : Base1(val), Base2(val2) {}
Hier initialisieren ich die Basisklassen explizit.

MyClass::MyClass() {}
Hier werden jeweils implizit die Standardkonstruktoren meiner beiden Basisklassen aufgerufen.

Gruß,

badday
 
Zuletzt bearbeitet:
Okey danke schonmal für die Antwort. Ich habe in letzer Zeit recht wenig mit C++ zutun gehabt und bin deshalb wohl nicht mehr ganz so fit.

Du schreibst ja, dass die Doppelpunkte zu einem normalen Methodenaufruf gehören. Ich kenne methodenaufrufe allerdings immer nur so (Was vieleicht auch daran liegt, dass ich mich wie schon erwähnt längere Zeit mit anderen Sprachen rum geschlagen habe..):

Klasseninstanz.EineMethode();

Wo ist jetzt der Unterschied zu:

Klasseninstanz::EineMethode();

Grüße Abcd
 
Wenn du ein Objekt der Klasse hast, z. B. MyClass a; so kannst du darauf a.methode(); aufrufen. Das liegt daran, da hier automatisch im Klassengütligkeitsbereich nach der Methode gesucht wird. Wenn du aber z. B. eine Elementfunktion definierst, musst du das mit :: machen. Es ist ja einfach (noch) kein Objekt vorhanden. Du deklarierst die Elementfunktion also in der Klasse, um sie dann von außerhalb zu definieren, benutzt du :: .

Beispiel:

class MyClass
{
//...
public:
bool func(int); //Deklaration

};

MyClass::func(int a) //Definition
{
//irgendetwas
}

Ich hoffe, das stimmt so^^.

Gruß,

badday
 
Okey danke, das von dir Beschriebene ist ja das normale Vorgehen, wenn man Deklaration und Definiton splitet, wie es ja üblich ist in C++. Also die Prototypen in der Headerdatei deklariert und die Definitonen in eine CPP Datei schreibt. In dem Fall, den ich meine geht es allerdings glaub ich noch in eine andere Richtung.

Ich kopiere mal einen kleinen Teil der Dokumentation:

Like many other classes in Angel, World uses the singleton pattern. What this means is that there can only
ever be one instance of this class in the program – if you think about it, this makes a lot of sense. So
you’ll never actually create the world directly.

Okey so weit verstehe, ich das noch ich kann also keine Insanzen von der Klasse erstellen..

Instead, you call the static function World::GetInstance(),
which returns a reference to the single world that has been created for your game. (Instead of using
World::GetInstance, you’ll find that we use a defined shortcut called theWorld.

Hier wird es nun kritisch. Kann ich nun irgendwo im Programm mit World::GetInstance(), eine Instanz erzuegen und Zugriff auf Funktionen von der Worldklasse benutzen? Sehe ich es richtig, dass ich hier den Doppelpunkt Operator benutzen muss, weil noch keine Insanz der Klasse exestiert, da man von der Klasse keine Instanzen erzeugt?

Wenn ich also jetzt eine Funktion der Klasse World aufrufen will (z. B. die Funktion Initialize) muss ich jetzt doch schreiben World::GetInstance()::Initialize() oder? Also mit World::GetInstance():: hohl ich mir den Zeiger um dann auf die Funktionen zugreifen zu können.

Nun haben die Programmierer glaub ich eine Art Terminius festgelegt um nicht immer World::GetInstance() schreiben zu müssen. Denn die Funktionen werden in der Beschreibung so aufgerufen (World::Initialize(); oder World::StartGame();).

Liege ich mit meinen Vermutungen richtig?
 
Zuletzt bearbeitet:
Irgendwie sind die Antworten hier unnötig kompliziert. Um auf die Frage kurz und knapp zu antworten:

Mit den doppelten Doppelpunkten kann man statische Methoden einer Klasse aufrufen. Beispiel:
Code:
      class Test {
      public:
        static void tuwas() {
          cout << "hallo";
        }
      };

      int main() {
        Test::tuwas();
      }

Ansonsten kann man mit dem :: auch durch Namensräume "navigieren". Wenn du zum Beispiel kein "using namespace std;" benutzt (was in fast jedem Tutorial aber der Fall ist), musst du auch immer "std::cout << "hallo";" schreiben. Aber das ist für deine Frage nicht wichtig.

So, nun zum Singleton: Wie kannst du das als Programmierer einer Klasse gewährleisten, dass nur ein Objekt deiner Klasse existiert? Auf jeden Fall kann der Konstruktur nicht public sein. Denn wenn er public wäre, kannst du nicht verhindern, dass der Benutzer deiner Klasse beliebig viele Objekte erzeugt, denn wenn der Konstruktor erstmal aufgerufen wurde, kannst du die Erzeugung des Objektes nicht mehr verhindern.

Du machst den Konstruktor also private, so dass er nur noch von deiner Klasse selber aufgerufen werden kann. Stattdessen machst du eine statische Methode, die public ist. Diese Methode kann den Konstruktor aufrufen und das Objekt zurückgeben. Der Vorteil ist nun, dass diese Methode vorher checken kann, ob bereits ein Objekt erzeugt wurde (einfach in einer statischen Variable speichern).

In deinem Beispiel wird das Objekt aber wohl nicht zurückgegeben, sondern wohl in einer privaten statischen Variablen gespeichert. World::initialize() erstellt wohl klassenintern ein neues Objekt und verwirft das alte. Das bedeutet, dass du selber niemals ein Objekt der Klasse World zu sehen bekommst. Du arbeitest ausschließlich mit den Klassenmethoden (die statischen Methoden). Die Klasse selber verwaltet intern das Objekt und sorgt so dafür, dass es nur eines gibt.
 
Zuletzt bearbeitet:
Okey danke schonmal. Zwei Fragen hab ich noch:

1. Muss es sein, das im Falle von der World Klasse intern eine Instanz erstellt wird? Soweit ich das verstehe ist es doch gar nicht nötig eine Instanz zu erstellen, wenn alle statischen Methoden mit Klasse::StaticMethod aufgerufen werden können.

2. Was mich jetzt auch noch verwirrt ist follgendes:

To do the initial setup of the world, we call the World::Initialize function.
theWorld.Initialize(1024, 768, "My Game", false);
This call opens a window to view the world – it’s 1024x768 with "My Game" in the title bar and antialiasing
disabled. Obviously you can swap out your own values and change the properties of the window.
After you call World::Initialize, you’ll want to do all your setup (adding Actors to the world), but nothing
will actually happen until you call World::StartGame(). This actually begins the game loop,

Wieso wird die Initialize Funktion hier auf zwei wegen Aufegrufen. Wenn sie Static ist wie kann sie dann wie eine normale Methode mit

Code:
theWorld.Initialize(1024, 768, "My Game", false);

aufgerufen werden?
 
Zu 1: Prinzipiell hast du recht, aber vielleicht ist World ja von irgendwas abgeleitet oder es ist einfach einfacher intern ein Objekt zu haben, weil man das dann einfach löschen und ein neues erstellen kann, wenn man es neu initialisieren möchte. Das kann viele Gründe haben.

2: Ich hab gerade rausgefunden, woher du das alles hast. (Google Code).
Es ist so, dass die ganzen Methoden außer "GetInstance()" gar keine statischen Methoden sind. In meinem vorherigen Beitrag kannst du den letzten Absatz also ignorieren :) Es ist eine klassiche Singleton-Architektur, bei der du dir per getInstance() selber das Objekt besorgen musst, um damit zu arbeiten. Die Methode gibt dir nur eben immer das selbe Objekt.

Wenn die schreiben "World::Initialize()", dann meinen die damit anscheinend einfach die Methode Initialize() eines World-Objektes. Ist vielleicht etwas ungünstig formuliert. Das ist also nicht als C++-Code zu verstehen.

"World::getInstance()" und "theWorld" ist übrigens in diesem Beispiel absolut identisch. Das liegt an einem #define am Anfang der Datei "World.h":
Code:
//singleton shortcut
#define theWorld World::GetInstance()

Du schreibst also entweder
Code:
theWorld.Initialize(...);
oder
Code:
World::GetInstance().Initialize(...);
. Ist in dem Fall genau das selbe.

Statische Methoden können übrigens nicht mit einem Punkt aufgerufen werden, um deine letzte Frage zu beantworten.
 
Zuletzt bearbeitet:
Zurück
Oben