"Komischer Fehler" beim verwenden eines std::vector<const char*> im Constructor
-
Hi Leute,
Ich bins mal wieder und hoffe, ihr könnt mir helfen. Ich schreibe gerade für eins meiner Projekte eine Texturen-Klasse. Jetzt bekomme ich den ziemlich komischen Fehler:In function `ZN7TextureC1EPKciji': undefined reference to `Texture::reusableIDs' undefined reference to `Texture::reusableIDs' undefined reference to `Texture::reusableIDs' undefined reference to `Texture::reusableIDs'Ich weiß, dass dieser Name(ZN7TextureC1EPKciji) schon aufgelöst ist und meiner Meinung nach für den Constructor meiner Textur-Klasse ist. Hier die Texturenklasse:
#ifdef __APPLE__ #include <GLUT/glut.h> #else #include <GL/glut.h> #endif #include "SOIL.h" #include "Defs.h" #include <vector> class Texture { public: Texture(const char* fileName, int forceChannels = 0, unsigned int flags = SOIL_FLAG_MIPMAPS, int wrapMode = GL_CLAMP) : textureWrapMode(wrapMode) { unsigned int reuseID = 0; if(reusableIDs.size() > 0) { reuseID = reusableIDs.front(); reusableIDs.erase(reusableIDs.begin()); } ID = SOIL_load_OGL_texture(fileName, forceChannels, reuseID, flags); if(ID == 0) { fileLoaded = false; ID = SOIL_load_OGL_texture("Resource\\FixMe.jpg", forceChannels, reuseID, flags); if(ID == 0) { throw FileNotFound(); } } else { fileLoaded = true; } int lastID; glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastID); glBindTexture(GL_TEXTURE_2D, ID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapMode); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapMode); glBindTexture(GL_TEXTURE_2D, lastID); } ~Texture() { reusableIDs.push_back(ID); } bool loadTexture(const char* fileName, int forceChannels = 0, unsigned int flags = 0) { unsigned int reuseID = 0; if(reusableIDs.size() > 0) { reuseID = reusableIDs.front(); reusableIDs.erase(reusableIDs.begin()); } ID = SOIL_load_OGL_texture(fileName, forceChannels, reuseID, flags); if(ID == 0) { fileLoaded = false; ID = SOIL_load_OGL_texture("Resource\\FixMe.jpg", forceChannels, reuseID, flags); if(ID == 0) { throw FileNotFound(); } } else { fileLoaded = true; } int lastID; glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastID); glBindTexture(GL_TEXTURE_2D, ID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapMode); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapMode); glBindTexture(GL_TEXTURE_2D, lastID); return true; } void openTexture() { glBindTexture(GL_TEXTURE_2D, ID); } private: unsigned int ID; int textureWrapMode; bool fileLoaded; static std::vector<unsigned int> reusableIDs; };
-
Statische Klassenelemente müssen auch irgendwo (einmalig!) definiert werden:
std::vector<unsigned int> Texture::reusableIDs;P.S.: Was passiert denn mit deiner reusableIDs-Liste, wenn jemand (absichtlich oder unabsichtlich) eine Textur kopiert oder zuweist? Schreckliche Dinge!
http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
-
... dir ist klar, dass du
reusableIDsaußerhalb der Klasse definieren musst?SeppJ schrieb:
Statische Klassenelemente müssen auch irgendwo (einmalig!) definiert werden
Nur wenn sie odr-used werden.
-
Sone schrieb:
... dir ist klar, dass du
reusableIDsaußerhalb der Klasse definieren musst?SeppJ schrieb:
Statische Klassenelemente müssen auch irgendwo (einmalig!) definiert werden
Nur wenn sie odr-used werden.
Was?
-
Sone schrieb:
... dir ist klar, dass du
reusableIDsaußerhalb der Klasse definieren musst?SeppJ schrieb:
Statische Klassenelemente müssen auch irgendwo (einmalig!) definiert werden
Nur wenn sie odr-used werden.
Was offenbar der Fall ist (6 mal wenn ich mich nicht verzählt habe).
-
camper schrieb:
Nur wenn sie odr-used werden.
Was offenbar der Fall ist (6 mal wenn ich mich nicht verzählt habe).
Mein Kommentar war, genau wie SeppJs Aussage, allgemein bezogen. (
)Noch eine Frage. Wieso gibt
loadTextureetwas zurück (der Rückgabewert ist immertrue, wenn die Funktion nicht durch eine Exception verlassen wird)?
Und wieso C-Strings? Darum.
-
Noch etwas, was SeppJs Blutzuckerpegel steigen lässt:
throw FileNotFound();Wieso gibst du keine ordentliche Fehlermeldung an? Lass die Leute doch wissen, welche Datei nicht gefunden wurde!

Weitere Kritikpunkte:
- Der Konstruktor und die
loadTexture-Funktion sind gleich. Machst du bestimmt aber sowieso selbst. - fileLoaded ist sinnfrei oder aber mindestens redundant. Deine Funktionen werden durch eine Exception verlassen, sobald die Datei nicht geladen werden konnte.
- Du willst keinen
std::vector, sondern eine**std::queue**. - Die ID einer Klasse sollte zudem
constsein [...]
Edit: Die wird ja in loadTexture zugewiesen... dann sollte das anders gemacht werden. Nur per Ctor zugewiesen...
class Texture { public: Texture(const char* fileName, int forceChannels = 0, unsigned int flags = SOIL_FLAG_MIPMAPS, int wrapMode = GL_CLAMP): textureWrapMode(wrapMode) { loadTexture( fileName, forceChannels, flags ); } ~Texture() { reusableIDs.push(ID); } bool loadTexture(const char* fileName, int forceChannels = 0, unsigned int flags = 0) { unsigned reuseID = 0; if( !reusableIDs.empty() ) { reuseID = reusableIDs.front(); reusableIDs.pop(); } ID = SOIL_load_OGL_texture(fileName, forceChannels, reuseID, flags); if(ID == 0) { ID = SOIL_load_OGL_texture("Resource\\FixMe.jpg", forceChannels, reuseID, flags); if(ID == 0) throw FileNotFound(); } int lastID; glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastID); glBindTexture(GL_TEXTURE_2D, ID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapMode); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapMode); glBindTexture(GL_TEXTURE_2D, lastID); } void openTexture() { glBindTexture(GL_TEXTURE_2D, ID); } private: unsigned ID; int const textureWrapMode; static std::queue<unsigned> reusableIDs; }; std::queue<unsigned> Texture::reusableIDs;
- Der Konstruktor und die
-
Sone schrieb:
Noch etwas, was SeppJs Blutzuckerpegel steigen lässt:
Welche Species ist das denn?
-
Sone schrieb:
Und wieso C-Strings?
Ich seh keinen Grund, hier std::string zu verwenden. Abgesehen von einer unnötigen Kopie würde das imo nichts bringen...
-
dot schrieb:
Sone schrieb:
Und wieso C-Strings?
Ich seh keinen Grund, hier std::string zu verwenden. Abgesehen von einer unnötigen Kopie würde das imo nichts bringen...

Sehe ich genauso. Wenn der nur an eine andere Funktion weitergeleitet wird, dann gibt es da kein Problem.
(Wieso habe ich das geschrieben?)
-
camper schrieb:
Sone schrieb:
Noch etwas, was SeppJs Blutzuckerpegel steigen lässt:
Welche Species ist das denn?
Eine sehr seltene, scherzhafte Bezeichnung des sogenannten Gelbbrustara. Der Witz besteht darin, dass er - sobald er SeppJs Wut spürt - sofort aufsteigt und einen sicheren Platz zum einstigen Verweilen sucht.
-
Hi,
Hatte ganz schön lange keine Zeit mehr hier her zu "gucken". Diese Variable(fileLoaded) sollte eigentlich nur dazu genutzt werden, um fest stellen zu können, ob die "richtige" Textur geladen wurde, oder ob die "FixMe.jpg" geladen wurde. Das die "loadTexture" ne boolsche Funktion ist, war noch ein Überbleibsel aus alten Zeiten. Die Exception wird nur geworfen, wenn noch nicht mal die "FixMe.jpg" gefunden wird -> Wenns nen Fehler bei der Installation gab. Siehe dazu auch den Thread in dem mir das vorgeschlagen wurde: http://www.c-plusplus.net/forum/318086.
Ehrlich gesagt hatte ich von std::queue noch nie was gehört :-/; Thx, wieder mal was gelernt
Und die ID sollte nicht const sein, dann könnte ich mir ja auch die "loadTexture" Funktion sparen... Ich sehe hier einfach keinen Sinn für ein "const".
(Hoffentlich habe ich jetzt nichts vergessen
)
MfG
DragonRaider