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

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

1

12.05.2016, 20:13

WinAPI | Class already exists

Hi,
ich habe ein ziemlich obskures Problem.

Ich habe zwei Klassen, 'Window' und 'Context'.
Der Konstruktor von 'Window' erstellt ein Fenster (WinAPI) und zeigt es an.
Der Konstruktor von 'Context' erstellt ebenso ein Fenster, das aber nur temporär ist. Dieses temporäre Fenster wird genutzt um OpenGL
Funktionen zu laden, nachdem dies abgeschlossen ist wird das temporäre Fenster gelöscht und ein Context für das eigentlich Fenster erstellt.

Wenn ich diese Konstruktoren nacheinander aufrufe, dann funktioniert alles wie es soll.
Also folgender Code:

C-/C++-Quelltext

1
2
Window window("Hello, bla bla", 600, 400);
Context context(window, parameter....);


So funktioniert das ganze.

Jedoch bin ich gerade dabei meinen Code zu refactoren...
Verschiebe ich den Konstruktoraufruf von Context an das Ende von dem Konstruktor von Window, dann bekomme ich plötzlich einen Error.
Laut 'GetLastError' handelt es sich bei der Exception um "Class already exists".

Folgendes funktioniert NICHT:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
Context::Context(const char* titel, int,...){
// Erstelle Fenster

pContext = new Context(*this); // Error ensteht hier.
// ENDE des Konstruktors
}

Window window(...);


Ich verstehe nicht wirklich wieso das nicht funktioniert. Der Visual Studio Debugger ist mir dabei nicht wirklich eine Hilfe.
Hatte jemand schon mal damit zu tun gehabt?

LG Julien

P.S.: Der Code schlägt tatsächlich bei 'RegisterClassEx' fehl.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Julién« (12.05.2016, 20:27) aus folgendem Grund: Vergewaltigung der deutschen Sprache


CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

2

12.05.2016, 21:14

Ich vermute, dass du zweimal das selbe Fenster mit dem Befehl RegisterClassEx registrierst. Um das zu überprüfen müsstest du mal die Konstruktoren der beiden Klassen posten.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

3

12.05.2016, 21:18

Darfst du im Konstruktor überhaupt *this benutzen? Das Objekt ist ja noch nicht vollständig erzeugt und du würdest damit eine Kopie anlegen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

12.05.2016, 21:26

Ich vermute, dass du zweimal das selbe Fenster mit dem Befehl RegisterClassEx registrierst. Um das zu überprüfen müsstest du mal die Konstruktoren der beiden Klassen posten.

this :rolleyes:

Darfst du im Konstruktor überhaupt *this benutzen? Das Objekt ist ja noch nicht vollständig erzeugt und du würdest damit eine Kopie anlegen.

Darf er; darf nur nicht auf noch nicht initialisierte Member/Basisklassensubobjekte zugreifen (sobald man im Body des C'tor ist, sind aber alle Member und Basisklassensubobjekte bereits initialisiert, lediglich das Objekt selbst gilt dann noch als nicht konstruiert).

Btw: *this allein legt keine Kopie an, erst wenn du das daraus erhaltene lvalue kopierst, legst du eine Kopie an. Das *this könnte in dem Fall hier aber beispielsweise auch einfach an eine Referenz gebunden werden...

5

12.05.2016, 21:41

*wiouwiouwiou*
Mein new-Detektor schlägt aus.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

6

13.05.2016, 10:17

Btw: *this allein legt keine Kopie an, erst wenn du das daraus erhaltene lvalue kopierst, legst du eine Kopie an. Das *this könnte in dem Fall hier aber beispielsweise auch einfach an eine Referenz gebunden werden...

So viel C++ Verständnis habe ich dann auch noch :) Dass das Objekt initialisiert ist ist mir soweit auch bewusst gewesen. Um darauf Einfluss zu nehmen hat man ja dann die Initialisierungslisten. Hatte dennoch im Kopf dass der Compiler da motzt.
*wiouwiouwiou*
Mein new-Detektor schlägt aus.

Auf jeden Fall :) Warum kein Smartpointer?
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

13.05.2016, 11:59

Auf jeden Fall :) Warum kein Smartpointer?

Ich würde sogar einen Schritt weiter gehen: Warum überhaupt ein Pointer?

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

8

13.05.2016, 12:05

Die Sache ist ja, dass ich ebene zweimal die gleiche Klasse registriere. Rufe ich die Konstruktoren hintereinander auf dann passiert nichts.
Für mich ist alles die gleiche Logik, egal ob ich die Konstruktoren direkt hintereinander oder ineinander aufrufe.

Seltsamerweise funktioniert alles, wenn ich die Konstruktoren hintereinander aufrufe.
Verschachtele ich die Konstruktoren, dann beschwert sich das Programm plötzlich.

Was auch interessant ist, dass ich einen "Class not found" Error bekomme (bzw. irgendwas, das so ähnlich heißt :thumbsup: ),
wenn ich die Klasse nur ein einziges mal im kompletten Ablauf registriere.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

13.05.2016, 12:07

Ohne den Code zu sehen, der das mit dem Klassen registrieren macht, wird man nicht viel dazu sagen können...

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

10

13.05.2016, 12:59

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
Window::Window(const char* pTitle,
                    uint32_t nWidth,
                    uint32_t nHeight,
                    bool bFullscreen,
                    bool bVisible){


        WNDCLASSEX  wc      = {};
        wc.cbSize           = sizeof(WNDCLASSEX);
        wc.hInstance        = GetModuleHandle(nullptr);
        wc.lpfnWndProc      = internal::WndProc;
        wc.lpszClassName    = pTitle;
        wc.style            = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;

        if(0 == RegisterClassEx(&wc)){
            //
            //  The exception class will contain the error code and
            //  a error description.
            //
            std::error_code err_code(GetLastError(), std::system_category());
            throw std::system_error(err_code);
        }


        if(true == bFullscreen){
            DEVMODE dmScreen    = {};
            dmScreen.dmSize     = sizeof(DEVMODE);

            for(int i = 0; EnumDisplaySettings(nullptr, i, &dmScreen); i++){
                if((dmScreen.dmPelsWidth == nWidth) && (dmScreen.dmPelsHeight == nHeight) && (dmScreen.dmBitsPerPel == 32)){
                    break;
                }
            }

            ChangeDisplaySettings(&dmScreen, CDS_FULLSCREEN);

        }

        pHandle = new internal::WindowHandle(nWidth, nHeight);

        RECT clientArea = { 0, 0, (long) nWidth, (long) nHeight};
        AdjustWindowRect(&clientArea, bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW, false);

        pHandle->handle = CreateWindowEx(
            bFullscreen ? WS_EX_APPWINDOW : NULL,
            pTitle,
            pTitle,
            bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW,    // NOTE: Perhaps I'll create a window config struct?
            GetSystemMetrics(SM_CXSCREEN) / 2,
            GetSystemMetrics(SM_CYSCREEN) / 2,
            clientArea.right    - clientArea.left,
            clientArea.bottom   - clientArea.top,
            nullptr,    // We're not having a parent window
            nullptr,    // nor a win32 menu.
            GetModuleHandle(nullptr),
            pHandle    // Is needed for the router 'WndProc'.
        );

        if(nullptr == pHandle->handle){
            delete pHandle;    // We don't want a memory leak, do we?
            std::error_code err_code(GetLastError(), std::system_category());
            throw std::system_error(err_code);
        }

        if(true == bVisible)
            ShowWindow(pHandle->handle, SW_SHOWDEFAULT);


Ich kann zwei Objekte von Window hintereinander erstellen, aber nicht ineinander.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Werbeanzeige