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

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

11

14.06.2008, 15:22

Zitat von »"knivil"«

Ob es nun ein Singleton von Meyers oder sonstwem ist, alle sind sie gleich gut, oder schlecht. Und der Heap, egal, da es fuer gewoehnlich nur einmal erstellt wird.


Das ist einfach, schlichtweg falsch.
@D13_Dreinig

riCo

Treue Seele

  • »riCo« ist der Autor dieses Themas

Beiträge: 165

Beruf: Student

  • Private Nachricht senden

12

14.06.2008, 22:04

Zitat von »"knivil"«

Brauchst du denn ein Singleton, oder reicht ein einfacher namespace?


Ein Namespace dient der Verhinderung von Namensüberschreitungen (Funktionen, Variablen, ...) und zur Einteilung von Quellcode in bestimmte Segmente.
Mit Singleton verhindere ich, dass es von einer Klasse mehrere Instanzen geben kann.

Was haben die beiden miteinander zu tun?

Zitat von »"knivil"«

Weisst du, was du da tust?

ich denke schon... und du? ;)
Wir leben alle unter dem Sternenhimmel, aber wir haben nicht alle den gleichen Horizont.

riCo

Treue Seele

  • »riCo« ist der Autor dieses Themas

Beiträge: 165

Beruf: Student

  • Private Nachricht senden

13

15.06.2008, 10:31

Ich bekomme diesen Linkerfehler einfach nicht raus. Vielleicht kann mir jemand helfen?

Der Header im DLL-Projekt(die Engine) ("elys_engine.h")

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Elysium_Engine.h

//


#if defined _MSC_VER && _MSC_VER >= 1020 
#pragma once 
#endif 

#ifndef __ELYSIUM_ENGINE_H_INCLUDED__
#define __ELYSIUM_ENGINE_H_INCLUDED__

// *** MACROS ***

#ifdef  ELYSIUM_DLL
#define ELYSIUM_API __declspec(dllexport)
#else
#define ELYSIUM_API __declspec(dllimport)
#endif


// *** INCLUDES ***

#include <windows.h>


namespace elysium
{
    
    #define ELYSIUM_DELETE_VARIABLE(x)   (delete   (x), x=NULL)
    #define ELYSIUM_DELETE_ARRAY(x)      (delete[] (x), x=NULL)
    
    
    template<class C>
    class ELYSIUM_API Singleton
    {
    private: 
        // Static current instance

        static C* CurrentInstance;
        
    public:
        // Current instance getter

        static C* Current()
        {
            if( Singleton<C>::CurrentInstance == NULL )
            {
                Singleton<C>::CurrentInstance = new C;
            }
            return Singleton<C>::CurrentInstance;
        }
        
        // Delete current instance

        static void DeleteCurrent()
        {
            if( Singleton<C>::CurrentInstance != NULL )
            {
                delete Singleton<C>::CurrentInstance;
                Singleton<C>::CurrentInstance = NULL;
            }
        }
    };
    
    // *** Basic Engine-class ***

    class ELYSIUM_API CElysium : public Singleton<CElysium> //elysium::Utilities::Singleton<CElysium>

    {
    public:
        int init();
        
        
    protected:
        
        
    };

} // end namespace elysium


#endif // __ELYSIUM_ENGINE_H_INCLUDED__


// **************************************************************************************************


Jetzt der Aufruf in der Anwendung:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// game.cpp

//


#pragma comment(lib,"..\\debug\\Elysium_Engine.lib")

#include <windows.h>
#include <winuser.h>
#include "elys_engine.h"



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow)
{
    UNREFERENCED_PARAMETER(hInstance);
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(szCmdParam);
    UNREFERENCED_PARAMETER(iCmdShow);
    
    MSG Message;
    
    
    // Engine und Spiel initialisieren.

    elysium::CElysium* pDieEinzigeInstanz = elysium::CElysium::Current();
    //p->init();

    
    
    // Nachrichtenschleife

    ZeroMemory(&Message, sizeof(MSG));
    while(Message.message != WM_QUIT)
    {
        while(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&Message);
            DispatchMessage(&Message);
        }
        
        // Bewegungen durchführen

        
        
        // Zeichnen

        
    }
    
    // Spiel beenden

    
    
    return (int)Message.wParam;
}

// **************************************************************************************************



Er gibt mir immer den Linkerfehler:
game.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""__declspec(dllimport) public: static class elysium::CElysium * __cdecl elysium::Singleton<class elysium::CElysium>::Current(void)" (__imp_?Current@?$Singleton@VCElysium@elysium@@@elysium@@SAPAVCElysium@2@XZ)" in Funktion "_WinMain@16".

Also es scheint an der Current-Methode zu liegen....
Wir leben alle unter dem Sternenhimmel, aber wir haben nicht alle den gleichen Horizont.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

14

15.06.2008, 10:56

Definier mal für den export ELYSIUM_DLL. Für den Import benötigst du selbstverständlich die .lib. Sonst gibst unaufgelöste externe Verweise...

Noch ein paar Tips:

C-/C++-Quelltext

1
2
3
4
5
6
#if defined _MSC_VER && _MSC_VER >= 1020
#pragma once
#endif

#ifndef __ELYSIUM_ENGINE_H_INCLUDED__
#define __ELYSIUM_ENGINE_H_INCLUDED__ 


Das kannst du umgekehrt schreiben, um dem Präprozessor Auswertungsaufwand abzunehmen:

C-/C++-Quelltext

1
2
3
4
5
6
#ifndef __ELYSIUM_ENGINE_H_INCLUDED__
#define __ELYSIUM_ENGINE_H_INCLUDED__

#if _MSC_VER >= 1020
#pragma once
#endif


Außerdem benötigst du deine erste Bedingung nicht.

Klassentemplates kannst du nicht in eine Dll exportieren. Daher ist dein ELYSIUM_API bei deinem Singletontemplate überflüssig.
@D13_Dreinig

Anonymous

unregistriert

15

15.06.2008, 11:06

C-/C++-Quelltext

1
2
    #define ELYSIUM_DELETE_VARIABLE(x)   (delete   (x), x=NULL)
    #define ELYSIUM_DELETE_ARRAY(x)         (delete[] (x), x=NULL) 

Nimm ein Template, das tut ja in den Augen weh.

Dann stopf noch ein

C-/C++-Quelltext

1
if (x != NULL)
rein, auch wenn delete NULL definiert ist, es heißt nicht das sich Compiler-Hersteller dran halten.

riCo

Treue Seele

  • »riCo« ist der Autor dieses Themas

Beiträge: 165

Beruf: Student

  • Private Nachricht senden

16

15.06.2008, 11:13

Ich habe das Problem gelöst. Die Templateklasse muss tatsächlich ohne ELYSIUM_API gekennzeichnet werden. Allerdings ist das nur die halbe Lösung. Das Problem war die statische Variable des Singletons.

C-/C++-Quelltext

1
2
template<class C>
C* Singleton<C>::CurrentInstance = 0;

... löste das Problem.
Wir leben alle unter dem Sternenhimmel, aber wir haben nicht alle den gleichen Horizont.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

17

15.06.2008, 11:16

Zitat von »"unsigned long"«


Dann stopf noch ein

C-/C++-Quelltext

1
if (x != NULL)
rein, auch wenn delete NULL definiert ist, es heißt nicht das sich Compiler-Hersteller dran halten.


Die meisten Compiler können das aber. Außerdem kann man durchaus darauf Vertrauen das bestimmte Fälle Standardkonform behandelt werden. Ansonsten würde z.T. sehr compilerspezifischer Code mit vielen speziellen Problembehandlungen entstehen (müssen).
Drum finde ich die Abfrage auf einen Nullzeiger, obzwar nicht störend, überflüssig.

Zitat von »"riCo"«

Ich habe das Problem gelöst. Die Templateklasse muss tatsächlich ohne ELYSIUM_API gekennzeichnet werden. Allerdings ist das nur die halbe Lösung. Das Problem war die statische Variable des Singletons.

C-/C++-Quelltext

1
2
template<class C>
C* Singleton<C>::CurrentInstance = 0;

... löste das Problem.


Nein, das ist wiederrum ein anderes Problem gewesen.
@D13_Dreinig

18

15.06.2008, 13:34

Eine Klasse dient zur Kapselung von Funktionalitaet, genau wie ein namespace. Ein Objekt speichert darueber hinaus Zustandsinformationen. Werden also keine Zustandsinformationen benoetigt werden, ist ein Singleton per se ueberfluessig.

Einfache Zustandsinformationen, wie eine Liste von Objekten etc., koennen auch lokal im namespace abgelegt werden, da sie sowieso nur einmal benoetigt/instanziiert werden.Deswegen ist es meist sinnvoller die benoetigten Funktion in einem namespace zu kapseln.

Und bevor alle gleich falsch und Bloedsinn schreinen, sollte erstmal ueber das Problem nachgedacht werden. Ja, ich weiss, was ich tue.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

19

15.06.2008, 13:50

Zitat von »"knivil"«


Und bevor alle gleich falsch und Bloedsinn schreinen, sollte erstmal ueber das Problem nachgedacht werden. Ja, ich weiss, was ich tue.


Ich bezog mich eher auf das:

Zitat von »"knivil"«


Ob es nun ein Singleton von Meyers oder sonstwem ist, alle sind sie gleich gut, oder schlecht. Und der Heap, egal, da es fuer gewoehnlich nur einmal erstellt wird.


Und das ist einfach nur falsch.
Schon das alle Singleton Implementationen gleich gut (oder schlecht) sein sollen ist Unfug. Es gibt viele, von der Funktionalität unterschiedliche, Implementationen. Und alle unterscheiden sie sich in vielen Details, ein Vergleich ist also extrem Unsinnig.

Und Allokationen auf dem Heap sind für gewöhnlich extrem Aufwändig. Da sollte man sich lieber zweimal überlegen ob man unnötige Resourcen verbrät, vor allem wenn eine gleichwertige Lösung existiert, die leichter zu implementieren, aber wesentlich weniger fehleranfällig ist.
@D13_Dreinig

Das Gurke

Community-Fossil

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

20

15.06.2008, 13:54

Deine Methode sind schlicht und einfach globale Variablen und haben mit Singletons daher nur am Rande was zu tun.

Namespaces sollen Namenskonflikte verhindern und nichts anderes! Sie sind nicht eingeführt worden um es Programmierern zu erleichtern, schlampigen Code zu verstecken!

Zitat

Namespace - zu deutsch Namensraum kennzeichnet Einheiten die zusammengehören. zB ist die gesamt C++ Standard Library im namespace std zu finden. Namespace verhindern Namenskonflikte und teilen den Code in logische Einheiten auf. Kaum einer kennt die Standard Library wirklich auswendig. Es kann also passieren, dass man für eine Klasse einen Namen verwendet, den es bereits gibt -> das führt zu Problmen. Es muss ja auch kein Namenskonflikt mit der Standard Bibliothek sein, man kann ja auch mit anderen Bibliotheken solche Probleme bekommen.

In C verwendete man Prefixe, also statt class Integer, schrieb man class myInteger. Sowas ist aber auf dauer unbefriedigend.

Werbeanzeige