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

1

07.06.2014, 19:52

[C++] Problem bei zugriff auf arry

Guten Tag,
Ich habe ein arry erstellt (sie Test1.cpp), und dies funktioniert auch.
Aber ich möchte von einem anderen script mit folgenden befehl auf das arry zugreifen.

C-/C++-Quelltext

1
App->SetResolution();

Dies funktioniert auch gut aber, damit kann ich nicht die werte vom arry auslesen.
Habe leider auch keine ahnung wie ich das machen könnte.


Test1.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
int* Application::SetResolution()
{
    if((ScreenWidthValue == 0)||(ScreenHeightValue==0))
    {
        int ResolutionArry[2] = {800, 600};
        return ResolutionArry;
    }
    else
    {
        int ResolutionArry[2] = {ScreenWidthValue, ScreenHeightValue};
        return ResolutionArry;
    }
}


Test1.hpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _app_H_
#define _app_H_

class Application
{
public:
    int* Application::SetResolution();
private:

};

#endif // _app_H_


Test2.cpp

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
#include <GLFW/glfw3.h>
#include <string>

#include "App.h"

using namespace std;

static Application *App;

int main(int argc, char** argv)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        exit(EXIT_FAILURE);

    if(!App -> InitEngineData(gContentPath))
        printf("Faild to Initialize the Engine Data! \n");

    App->SetResolution();
    printf("%d \n", App->SetResolution());
    
    /* Create a window and its OpenGL context */
    if(!App->SetScreenMode())
        window = glfwCreateWindow(640, 480, "", NULL, NULL);
    else
        window = glfwCreateWindow(640, 480, "", glfwGetPrimaryMonitor(), NULL);

    glfwSetWindowTitle(window, "");
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    // Initialize Render Engine
    App -> InitRenderEngine();

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

07.06.2014, 19:56

Das geht nicht. Du kannst nicht die Adresse einer lokalen Variable zurückgeben, damit jagst Du Dein Programm zur Hölle. Entweder Du erstellst den Array auf dem Heap oder Du verwendest eine moderne Datenstruktur.
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]

3

07.06.2014, 20:16

Was ist bitte heap und was sind modernere datenstrucktuten?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

07.06.2014, 20:24

Du hast im Prinzip zwei Speicherbereiche:
1) Der Stack. Dort legen alle Deine Methoden und Variablen ihre lokalen Variablen ab. Liegen Klassen/Structs auf dem Stack, liegen auch ihre Member auf dem Stack. Er wächst mit jedem weiter verschachteltem Funktionsaufruf weiter.
2) Der Heap. Das ist ein spezieller Daten-Bereich, in welchem nur Daten liegen. Den Speicher dafür musst Du mit "new" manuell anfordern oder Datenstrukturen nutzen, die das für Dich tun.

Gibst Du Adressen auf Variablen im Stack zurück und schreibst darin herum, dann sind diese Werte futsch, sobald du genug weitere Funktionen aufrufst. Stell es dir so vor, dass du eine Treppe hast und ganz unten stehst. Jeder Funktionsaufruf bringt dich eine Stufe höher und jede Variable auch. Stehst Du nun auf Stufe 5, schreibst die wichtigen Infos dahin und Du packst nun Variable X in Stufe 6 rein und verlässt die Funktion wieder, dann stehst Du auf Stufe 4 und glaubst auf Stufe 6 sei nun noch X. Das geht so lange gut, bis eine andere Funktion auf Stufe 5 klettert und auf Stufe 6 was eigenes ablegen will. Die weiß ja nicht, dass Du vorher mal da warst und überschreibt Dir nun X mit was ganz anderem. Wer auch immer X verwendet, hat nun ein arges Problem, denn er benutzt irgendwas, aber nicht das, was mal in X war.

Abhilfe bringt Dir da statt einem int* oder int[] ein std::vector<int> oder ähnliches. Die kümmern sich darum, dass ihre Inhalte sicher sind und beim Verlassen von Funktionen richtig kopiert werden. Du darfst dann natürlich keinen Pointer zurückgeben, sondern wirklich den Vector selbst.
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]

5

07.06.2014, 21:16

Um mal bei der klassischen Lösung zu bleiben:

C-/C++-Quelltext

1
int ResolutionArry* = new int[] {800, 600};


Du musst dann aufpassen, dass dieser int-buffer wieder freigegeben wird (delete[] ResolutionArry).
Das ist allerdings sehr umständlich für den Programmierer, um immer darauf zu achten, wie lange dieses Array "lebt".

Darum wurden einerseits die "modernen Lösungen" geschaffen.
Ich würde dir aber in deinem Fall zu einer viel einfacheren Lösung raten: structs

C-/C++-Quelltext

1
2
3
4
struct SResolution
{
    int w, h;
} resolution;


.. bevor du mit irgendwelchen Arrays rumhantierst. Das ist dann auch für Programmierer deutlich angenehmer zu lesen.
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

07.06.2014, 21:22

Hehe, ich hätte mal auf den konkreten Use-Case schauen sollen. Ein Struct ist hier natürlich die richtigere Wahl.
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]

7

09.06.2014, 19:32

Danke für die Tipps.
Ich habe auf struct in einer Header datei umgeändert.

App.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
#ifndef _app_H_
#define _app_H_

#include <string>

struct SResolution {
  int w;
  int h;
};
 
extern struct SResolution resolution;
using namespace std;
    extern string gContentPath;

class Application
{
public:
    bool Application::InitEngineData(string gContentPath);
    bool Application::InitRenderEngine();
    void Application::release();
    bool Application::SetWindowTitle();
    bool Application::SetScreenMode();
    void Application::SetResolution();
private:

};

#endif // _app_H_


App.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "app.h"
#include "XmlPraser\pugixml.hpp"

#include <string>
#include <iostream>

using namespace std;

void Application::SetResolution()
{
    if((ScreenHeightValue == 0)||(ScreenWidthValue == 0))
    {
        struct SResolution resolution = { 800, 600 };
    }
    else
    {
        struct SResolution resolution = { ScreenWidthValue, ScreenHeightValue };
    }

}


Andere.cpp

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
#include <GLFW/glfw3.h>
#include <string>

#include "App.h"

using namespace std;

static Application *App;

// trims the app path and navigates to content folder
string getContentPath( char *fullPath )
{
        string s( fullPath );
        if( s.find( "/" ) != string::npos ) s = s.substr( 0, s.rfind( "/" ) );
        else if( s.find( "\\" ) != string::npos ) s = s.substr( 0, s.rfind( "\\" ));
        s.append("\\..\\res");      // Change this when content is located on a different location! Path is always relative
        return s;
}
 

int main(int argc, char** argv)
{
    string gContentPath =  getContentPath(argv[0]);

    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        exit(EXIT_FAILURE);

    if(!App -> InitEngineData(gContentPath))
        printf("Faild to Initialize the Engine Data! \n");

    App->SetResolution();
    
    /* Create a window and its OpenGL context */
    if(!App->SetScreenMode())
        window = glfwCreateWindow(640, 480, "", NULL, NULL);
    else
        window = glfwCreateWindow(640, 480, "", glfwGetPrimaryMonitor(), NULL);

    glfwSetWindowTitle(window, "");
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    // Initialize Render Engine
    App -> InitRenderEngine();

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        printf("%d\n", resolution.h);
        printf("%d\n", resolution.w);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}


Dies löst zwei fehler aus, was mir ein rätsel ist.

Quellcode

1
2
Fehler  7   error LNK1120: 1 nicht aufgel÷ste Externe  E:\Projekte\C++ Projekts\Client\Debug\Client.exe    1   1   Client
Fehler  6   error LNK2001: Nicht aufgel÷stes externes Symbol ""struct SResolution resolution" (?resolution@@3USResolution@@A)".    E:\Projekte\C++ Projekts\Client\Client\MainFramework.obj    Client

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

09.06.2014, 20:07

Du hast eine externe Variable namens "resolution" vom Typ "SResolution" deklariert, aber nirgends definiert. Zudem machen Zeile 13 und 17 im zweiten Listing keinen Sinn. Warum Du den Rückgabewert abgeschafft hast und stattdessen eine globale Variable verwenden willst ist mir nicht ganz klar. Dir?

Zudem ist Deine Syntax C-Style (z.B. Zeile 11 im ersten Listing) oder Du hast was falsches gelernt.
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]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (09.06.2014, 20:13)


9

09.06.2014, 20:40

C-/C++-Quelltext

1
2
3
4
5
6
class Application
{
public:
    bool Application::InitEngineData(string gContentPath);
... 
} ;
das kompiliert? Oo
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

10

09.06.2014, 20:43

Mit dem Visual Studio Compiler, ja. ;)
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Werbeanzeige