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

sw1

Frischling

  • »sw1« ist der Autor dieses Themas
  • Private Nachricht senden

1

08.01.2016, 21:12

static multimap

Hallo liebes spieleprogrammierer.de Forum.

Ich möchte die folgende Klasse schreiben:


Die .h Datei:

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
#pragma once
#include <SFML\Graphics.hpp>

class collectedSprite
{
public:
    collectedSprite(int layer);
    ~collectedSprite();

    sf::Sprite* mSprite;

/*
...
*/

private:
    static std::multimap<int, sf::Sprite*> allSprites;

    int layer;

/*
...
*/

};



Die .cpp Datei:


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
#include "collectedSprite.h"

collectedSprite::collectedSprite(int layer) : layer(layer)
{
    sf::Sprite* newSprite = new sf::Sprite;
    allSprites.insert(std::pair<int, sf::Sprite*>(layer, newSprite));
    mSprite = newSprite;
}


collectedSprite::~collectedSprite()
{
    for (auto it = allSprites.find(layer); it != allSprites.end(); it++)
    {
        if (it->second == mSprite)
        {
            allSprites.erase(it);
            break;
        }
    }

    delete mSprite;
    mSprite = nullptr;
}

/*
...
*/



Die Klasse soll später noch weitere Member / Funktionen bekommen, dass oben gezeigte ist aber für mein Problem relevant.

Wenn ich das so kompiliere kommt die folgende Fehlermeldung: "Das System kann die angegebene Datei nicht finden". Wenn ich das static entferne funktioniert alles. Was ist hier das Problem?

Die Klasse soll eine Art Erweiterung zur sf :: Sprite Klasse sein. Ich möchte durch ein Objekt meiner Klasse collectedSprite im Prinzip nur ein sf :: Sprite erstellen, welches gleich in einen Container, mit der Information in welcher "Schicht" es gezeichnet werden soll, kommt.

Viele Grüße

Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von »sw1« (08.01.2016, 21:41) aus folgendem Grund: Unbeabsichtigt abgeschickt und Fehlerkorrekturen.


2

09.01.2016, 09:02

Um deine Frage zu Beantworten, du must deine Static Variable Initialiseren..

Was du bisher geschrieben hast sieht Fragwürdig aus.

1.

C-/C++-Quelltext

1
for (auto it = allSprites.find(layer); it != allSprites.end(); it++)

Normal sollte allSprites.find durch allSprites.begin() ersetzt werden, bin mir hier nicht Sicher ob mit find das erste Elment im Kontainer auf anhieb gefunden wird.

Zitat von »http://www.cplusplus.com/reference/map/multimap/find/«

Notice that this function returns an iterator to a single element (of the possibly multiple elements with equivalent keys). To obtain the entire range of equivalent elements, see multimap::equal_range.

2.

C-/C++-Quelltext

1
sf::Sprite* newSprite = new sf::Sprite;
unnötig die Sprites auf dem Heap zu erzeugen der Stack reicht da völlig. Und wenn Heap dann sollten Smartpointer benutzt werden.

Das ganze ließe sich sicher auch anders lösen, habe nur noch nicht ganz verstanden was du genau vorhast.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

3

09.01.2016, 09:42

Um deine Frage zu Beantworten, du must deine Static Variable Initialiseren..

Eine statische Membervariable muss nicht initialisiert werden. Sie mussen aber definiert werden. Ueber fehlende Definitionen kann sich aber nur der Linker beschwerden. Hier tritt der Fehler aber angeblich beim kompilieren auf. Von daher kann man auf die Frage eigentlich keine sinnvolle Antwort geben, ausser zu raten.

Mein Vorschlag daher: Der OP sollte die Basics von C++ lernen sowie mit seiner IDE umzugehen, damit er beim naechsten Mal sein Problem vernuenftig schildern kann.

4

09.01.2016, 10:22

ausser zu raten

Das war es in der Tat, da es hier das weglassen von static den Fehler beseitigt.

Und ob der Linker oder der Compilier den Fehler ausgibt, wird unter umständen dem TE nicht bewust sein.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

sw1

Frischling

  • »sw1« ist der Autor dieses Themas
  • Private Nachricht senden

5

09.01.2016, 14:10

Ersteinmal danke für eure Antworten.

Zitat

Normal sollte allSprites.find durch allSprites.begin() ersetzt werden, bin mir hier nicht Sicher ob mit find das erste Elment im Kontainer auf anhieb gefunden wird.

Habe ich schonmal geändert.

Zitat

unnötig die Sprites auf dem Heap zu erzeugen der Stack reicht da völlig. Und wenn Heap dann sollten Smartpointer benutzt werden.

Über die Smartpointern muss ich mich erst noch weiter Informieren, deswegen will ich es zunächst so machen.

Zitat

Das ganze ließe sich sicher auch anders lösen, habe nur noch nicht ganz verstanden was du genau vorhast.

Meine Klasse soll im Prinzip nur ein Sprite sein, der die Information enthält, in welcher "Schicht" er gezeichnet werden soll (d.h. welche Sprites als erstes und welche erst später gezeichnet werden). In der static std::multimap<int , sf :: Sprite*> werden dann alle Sprites durch Pointer zentral gesammelt. Dann sollte es noch eine Funktion zum zeichnen aller Sprites geben:

C-/C++-Quelltext

1
2
3
4
5
6
7
void collectedSprite::drawAllSprites(sf::RenderWindow& fenster)
{
    for (auto it = allSprites.begin(); it != allSprites.end(); it++)
    {
        fenster.draw(*it->second);
    }
}


Damit ließen sich alle Sprites in der gewünschten Reihenfolge zeichnen.


Zitat

Eine statische Membervariable muss nicht initialisiert werden. Sie mussen aber definiert werden. Ueber fehlende Definitionen kann sich aber nur der Linker beschwerden. Hier tritt der Fehler aber angeblich beim kompilieren auf. Von daher kann man auf die Frage eigentlich keine sinnvolle Antwort geben, ausser zu raten.

Mein Vorschlag daher: Der OP sollte die Basics von C++ lernen sowie mit seiner IDE umzugehen, damit er beim naechsten Mal sein Problem vernuenftig schildern kann.


Zitat

Und ob der Linker oder der Compilier den Fehler ausgibt, wird unter umständen dem TE nicht bewust sein.

Genau weiß ich nicht ob es beim kompilieren oder beim Linker das Problem gibt, hatte mich im ersten Beitrag da falsch ausgedrückt. Mir wird noch folgende Fehlermeldung ausgegeben:

1>collectedSprite.obj : error LNK2001: Nicht aufgel÷stes externes Symbol ""private: static class std::multimap<int,class sf :: Sprite *,struct std::less<int>,class std::allocator<struct std::pair<int const ,class sf :: Sprite *> > > collectedSprite::allSprites" (?allSprites@collectedSprite@@0V?$multimap@HPAVSprite@sf@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHPAVSprite@sf@@@std@@@4@@std@@A)".
1>textButton.obj : error LNK2001: Nicht aufgel÷stes externes Symbol ""public: virtual void __thiscall textButton::activityCheck(class sf::RenderWindow &)" (?activityCheck@textButton@@UAEXAAVRenderWindow@sf@@@Z)".
1>C:\Users\Walther\Documents\Visual Studio 2015\Projects\Gravitation\Debug\Gravitation.exe : fatal error LNK1120: 2 nicht aufgel÷ste Externe

Wahrscheinlich hat dann wohl der Linker das Problem, soweit ich das verstehe. Zur Information, ich nutze Visual Studio 2015.


Ich habe mir den Link von oben mal angesehen. Warum genau muss die statische Membervariable nun initialisiert (bzw. definiert?) werden? wenn ich das static entferne läuft ja auch alles durch und ich erhalte zunächst einfach einen leeren Container.
Wie genau kann ich die static std::multimap<int , sf :: Sprite*> nun initialisieren bzw. definieren?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »sw1« (09.01.2016, 14:15) aus folgendem Grund: Fehlerkorrektur


6

09.01.2016, 15:47

Hier in diesem Topic geht es genau um das selbe problem. Soviel sei mal verraten so wie du es plannst ist es eine schlechte idee.

Ich habe mir den Link von oben mal angesehen. Warum genau muss die statische Membervariable nun initialisiert (bzw. definiert?) werden? wenn ich das static entferne läuft ja auch alles durch und ich erhalte zunächst einfach einen leeren Container.


Nun das gehört eigentlich zu den Grundlagen von den TGGC spricht ;)

Eine Statische Membervariable "existiert" schon bevor überhaupt eine Instanz der Klasse erstellt wird, also muss sie auch schon defeniert werden bevor eine Instanz der Klasse erstellt wird. Deshalb definert man sie im Normalfall in der dazugehörigen cpp-Datei der Klasse.

Edit:
Wie genau kann ich die static std::multimap<int , sf :: Sprite*> nun initialisieren bzw. definieren?


C-/C++-Quelltext

1
2
// in der cpp Datei
std::multimap<int, sf::Sprite*> collectedSprite::allSprites;


Aber wie Gesagt ich rate dir von diese Design ab.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Koschi« (09.01.2016, 16:14)


sw1

Frischling

  • »sw1« ist der Autor dieses Themas
  • Private Nachricht senden

7

09.01.2016, 21:09

Danke für die Antwort, es funktioniert.
Ich werde mich mal weiter Informieren und schauen ob ich es anders mache oder doch so versuche :) .

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

8

09.01.2016, 22:05

Genau weiß ich nicht ob es beim kompilieren oder beim Linker das Problem gibt, hatte mich im ersten Beitrag da falsch ausgedrückt. Mir wird noch folgende Fehlermeldung ausgegeben:

1>collectedSprite.obj : error LNK2001: Nicht aufgel÷stes externes Symbol ""private: static class std::multimap<int,class sf :: Sprite *,struct std::less<int>,class std::allocator<struct std::pair<int const ,class sf :: Sprite *> > > collectedSprite::allSprites" (?allSprites@collectedSprite@@0V?$multimap@HPAVSprite@sf@@U?$less@H@std@@V?$allocator@U?$pair@$$CBHPAVSprite@sf@@@std@@@4@@std@@A)".
1>textButton.obj : error LNK2001: Nicht aufgel÷stes externes Symbol ""public: virtual void __thiscall textButton::activityCheck(class sf::RenderWindow &)" (?activityCheck@textButton@@UAEXAAVRenderWindow@sf@@@Z)".
1>C:\Users\Walther\Documents\Visual Studio 2015\Projects\Gravitation\Debug\Gravitation.exe : fatal error LNK1120: 2 nicht aufgel÷ste Externe
Ja und warum verschweigst du uns dann die Fehlermeldungen? Oder meintest du echt "Datei nicht gefunden" wuerden schon reichen?

Und BTW schonmal nachgedacht was "error LNK2001" bedeuten koennte? Oder vielleicht mal gegoogled? Da braeuchte man vlt. auch nicht spekulieren obs beim kompilieren ein Problem gab.

Du erwartest von uns doch auch nuetzliche Antworten, da macht mich so ein Verhalten echt aergerlich.

Desweiteren halte ich dein Design fuer ein voelliges Fehldesign! Warum nicht eine Klasse Layer mit einem Vektor/Liste von Sprites und dann wieder eine Klasse LayerContainer mit einem vector/map der Layer? Was wuerde wohl passieren, wenn du mal deine Layermap paralell brauchst, z.b. in einem Spiel mit Splitscreen oder wo man einfach zwischen 2 Modis umschalten (z.B. Uebersichtskarte und Kampfbildsschirm)? Dann musst du alles schoen umschreiben weil es ja nur eine globale Liste gibt mit deiner statischen Map.

sw1

Frischling

  • »sw1« ist der Autor dieses Themas
  • Private Nachricht senden

9

10.01.2016, 11:58

Zitat

Ja und warum verschweigst du uns dann die Fehlermeldungen? Oder meintest du echt "Datei nicht gefunden" wuerden schon reichen?

Dies war mir zunächst nicht bewusst und ich habe in meinen beiden bisherigen Beiträgen versucht das Problem so gut wie möglich darzustellen ;) .

Zitat

Desweiteren halte ich dein Design fuer ein voelliges Fehldesign! Warum nicht eine Klasse Layer mit einem Vektor/Liste von Sprites und dann wieder eine Klasse LayerContainer mit einem vector/map der Layer? Was wuerde wohl passieren, wenn du mal deine Layermap paralell brauchst, z.b. in einem Spiel mit Splitscreen oder wo man einfach zwischen 2 Modis umschalten (z.B. Uebersichtskarte und Kampfbildsschirm)? Dann musst du alles schoen umschreiben weil es ja nur eine globale Liste gibt mit deiner statischen Map.


Müsste ich hierbei nicht eine Referenz an alle Objekte, die einen sf :: Sprite enthalten, des LayerContainers übergeben? Sollten dann tatsächlich die Sprites oder nur Pointer auf die Sprites, welche sich dann in vielen anderen Objekten befinden, im LayerContainer enthalten sein?
Wenn die Sprites im LayerContaier enthalten wären müsste ich diesen ja auch bei sämtlichen Funktionen eines Objekts (z.b. dem Spieler, Gegner) als Referenz übergeben und hierdrin den richtigen Sprite suchen, dass wäre sehr aufwendig.
Wenn Pointer auf die Sprites im LayerContainer enthalten wären müsste ich zumindest im Constructor und Destructor den LayerContainer als Referenz übergeben.
Bei beiden Möglichkeiten stelle ich es mir recht umständlich vor, oder habe ich das ganze falsch verstanden?

Werbeanzeige