Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

TigerClaw25

unregistriert

1

10.07.2017, 15:21

Singleton

Ich bin jetzt beim Thema Singletons auf Seite 249-250. Leider komme ich vom Verständnis her absolut nicht mit, obwohl ich die Themen davor gut verstanden und aufgenommen habe. Hier erst einmal der Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef TSINGLETON
#define TSINGLETON

template <class T>
class TSingleton {
protected:
    // Membervariable
    static T *m_pSingleton;

public:
    virtual ~TSingleton()
    {
    }

    inline static T* Get(){
        if (!m_pSingleton)
            m_pSingleton = new T;
        
        return m_pSingleton;
    }

    static void Del(){
        if (m_pSingleton){
            delete (m_pSingleton);
            m_pSingleton = NULL;
        }
    }
};


template <class T>
T* TSingleton<T>::m_pSingleton = 0;

#endif


und die main:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include "Singleton.hpp"

using namespace std;

class CLogfile : public TSingleton<CLogfile>{
public:
    CLogfile(){
        cout << "Konstruktor aufgerufen" << endl;
    }

    ~CLogfile(){
        cout << "Destruktor aufgerufen" << endl;
    }

    void Statusmeldung(){
        cout << "Irgend ein Status" << endl;
    }
};

void Funktion(){
    CLogfile::Get()->Statusmeldung();
}

int main(){

    Funktion();

    CLogfile::Del();

    system("Pause");
    return 0;
}


Die Schreibweise ist für mich momentan derart verwirrend, dass ich nichts mehr verstehe. Ich kann dem Code nicht ganz folgen. Meine erste Frage bezieht sich auf die Funktion "Funktion()". Doret wird im Buch der "::" Operator verwendet. Dadurch erlangt man Zugriff auf die Funktion der Singleton-Klasse aus der "Header-Datei". Das verstehe ich nicht, denn:
1. Der "::"-Operator wurde bisher verwendet, um Memberfunktionen und -variablen außerhalb der Klassendeklaration zu definieren (das habe ich verstanden)
2. um statische Membervariablen außerhalb der Klasse zu definieren (ich glaube, weil eine Definition innerhalb der Klassendeklaration dazu führen würde, dass diese immer neu initialisiert werden würden, was ja nicht Sinn und Zweck von statischen Varialen ist)

Wie kommt es, dass der "::" nun innerhalb einer Funktion verwendet werden kann? Meine erste Frage ist, ob der Zugriff außerhalb einer Klasse über "::" sowohl für Memberfunktionen als auch Membervariablen gilt, jedoch nur wenn es statische Elemente sind? Davon gehe ich momentan aus. Warum auch immer. Meine zweite Frage ist, wie das überhaupt möglich sein kann, da der Zugriff über die Funktion "Funktion()" geschieht. Ist das dann nicht "lokal"? Müsste der Zugriff nicht global außerhalb der Funktion stattfinden?
Und wie ist es überhaupt möglich "CLogfile::Get()->Statusmeldung();" auszuführen? CLogfile ist eine Klasse bzw. eine Schablone. Funktioniert das nicht erst, wenn ich eine Instanz habe wie CLogfile Logfile1; ?

TigerClaw25

unregistriert

2

10.07.2017, 15:48

Nachtrag. Wenn ich alles bisher richtig verstanden habe, kann man auf Methoden und Attribute von Klassen auch ohne eine Instanz zugreifen, aber das geht nur bei statischen Memberfunktionen - und -variablen, weil da der Speicher da bereits reserviert wird. Und im Falle von "Get()" geschieht die deklaration und Definition in der Klasse, sodass bereits eine Adresse exisiert.

Tobiking

1x Rätselkönig

  • Private Nachricht senden

3

10.07.2017, 15:51

Das verstehe ich nicht, denn:
1. Der "::"-Operator wurde bisher verwendet, um Memberfunktionen und -variablen außerhalb der Klassendeklaration zu definieren (das habe ich verstanden)
2. um statische Membervariablen außerhalb der Klasse zu definieren (ich glaube, weil eine Definition innerhalb der Klassendeklaration dazu führen würde, dass diese immer neu initialisiert werden würden, was ja nicht Sinn und Zweck von statischen Varialen ist)

Das "::" ist einfach nur ein Trenner wenn du einen Pfad zu einem Bezeichnet angeben willst der verschachtelt ist. Klasse A in Namespace N ist N::A. Funktion f in A ist dann N::A::f usw. Je nachdem in welcher Ebene du dich gerade befindest musst du mehr oder weniger Teile dieses Pfades angeben.

Das ist zudem unabhängig vom Definieren. In dem Beispiel wird der Pfad z.B. verwendet um eine statische Funktion aus einer Klasse aufzurufen.


Und wie ist es überhaupt möglich "CLogfile::Get()->Statusmeldung();" auszuführen? CLogfile ist eine Klasse bzw. eine Schablone. Funktioniert das nicht erst, wenn ich eine Instanz habe wie CLogfile Logfile1; ?

Die Klasse besitzt eine Instanz von sich selbst: m_pSingleton. Mit CLogfile::Get() bekommst du diese Instanz und kannst darauf natürlich wie auf jede selbst erstellte Instanz die Methoden ausführen.

TigerClaw25

unregistriert

4

10.07.2017, 16:15

An sich kann ich mir den Code mittlerweile erklären, aber verwirrend ist es zu Beginn trotzdem.

5

10.07.2017, 18:10

Du solltest dir auf jeden Fall, weshalb dieser Code höchst fehlerhaft ist und warum ein Singleton keine Ersatz für globale Variablen sind.

TigerClaw25

unregistriert

6

10.07.2017, 20:39

Was hat es eigentlich mit Zeile 22 "CLogfile::Get()->Statusmeldung();" auf sich?

Ich kenne bei Zeiger als Rückgabetyp einer Funktion nur folgendes Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
int *funktion(void) {
    int zahl = 3;
    int *zeiger = &zahl;
    return zeiger;           /* hier wird ein Zeiger zurückgegeben */
}
main() {
    int *ptr;
    ptr= funktion();
  
}

Ich kenne das so, dass der Rückgabewert bei diesem Beispiel die Anfangsadresse ist. Diese wird zurückgegeben. Speichern tue ich diese Adresse in "ptr". Diese Zeile hier kann ich jedoch nicht interpretieren?

C-/C++-Quelltext

1
CLogfile::Get()->Statusmeldung();


Bräuchte ich nicht eine Art Zeigervariable wie "ptr", um das wie folgt zu tun:

C-/C++-Quelltext

1
2
ptr = CLogfile::Get();
ptr->Statusmeldung();


Bewirkt das das selbe? Falls ja, wieso schreibt man in Bücher "ptr=funktion()" statt einfach "funktion()" ohne Zuweisung des Rückgabewers an eine andere Zeigervariable?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

10.07.2017, 21:16

Gib niemals (!!!) einen Pointer oder eine Referenz auf eine lokale Variable zurück! Diese Variable existiert nämlich nach dem Verlassen der Funktion nicht mehr.
Davon mal abgesehen brauchst du keine Zuweisung an eine Variable. Es kommt ein Pointer zurück. Den kannst du direkt verwenden, ohne ihn erst in eine Variable zu kopieren.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TigerClaw25

unregistriert

8

10.07.2017, 22:33

Das wird aber in jedem Beispiel so gezeigt:
https://de.wikipedia.org/wiki/Zeiger_in_…_einer_Funktion
http://openbook.rheinwerk-verlag.de/c_vo…a762880b480283f

Wahrscheinlich, weil man sich an den normalen lokalen variablen und den normalen Rückgabewerten von FUnktionen orientiert?!

Tobiking

1x Rätselkönig

  • Private Nachricht senden

9

10.07.2017, 22:49

Die Beispiele zeigen undefiniertes Verhalten. Sie funktionieren in manchen Fällen, weil der Stackbereich nach dem Zurückkehren aus der Funktion nicht überschrieben wird. Das ist aber nicht garantiert und je nach Compiler/System kann das also schiefgehen. Spätestens in einem normalen Programm wird das schiefgehen.

Zum Thema Jürgen Wolf Bücher gibt es im C++ Forum einiges: https://www.c-plusplus.net/forum/272350-full. Da ist sogar genau das Beispiel genannt.

Das die Wikipedia auf dem gleichen Niveau ist, ist Schade. In den Diskussionen wird sogar erwähnt, dass das Beispiel undefiniertes Verhalten ist.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

10

10.07.2017, 23:30

Ich habe das Beispiel bei Wikipedia jetzt mal auf die einfachste Art repariert, die mir einfiel: static int zahl statt int zahl.

Werbeanzeige