Verweigerte Ausgabe
-
wenn tatsächlich keine ausgabe stattfindet, würde ich sagen der compiler ist nicht standardkonform. Nimm ein anderen Compiler, sofern du auf die WinAPI verzichten kannst. Das GUI kannst du auch mit Qt oder Gtk oder so erzeugen
-
@ Maxi: Dann erfolgt die Ausgabe ganz normal.
Hatte noch nie jemand so ein Problem? Mich wundert die ganze Sache nur ein bisschen, da ich Visual C++ 6 eigentlich für einen guten Compiler gehalten habe...und ein Umstieg wäre irgendwie nervig, da wir in der Schule auch Visual C++ installiert haben und ich mich dann immer umgewöhnen müsste.
Aber wenn es denn schon sein muss - wer kann mir einen guten, kostenlosen Compiler empfehlen?
-
Zweiundvierzig schrieb:
Mich wundert die ganze Sache nur ein bisschen, da ich Visual C++ 6 eigentlich für einen guten Compiler gehalten habe.
VC6 ist vor allem eines: alt. Hast du das neueste Service Pack für VC6 installiert?
Ich bin mir aber ziemlich sicher, dass es nicht am Compiler, sondern an deinem Code liegt. Zeig doch mal die Definition von Container, wenn's nicht zu viel ist.
-
Dacht ich mir auch. Gerade habe ich festgestellt, dass ich keine Datei erstellen kann - er akzeptiert den Code, aber erstellt trotzdem keine Datei.

Hier der Code:
#ifndef CONTAINER_H #define CONTAINER_H #include <vector> #include <string> typedef unsigned short us; template <class T> class Container { public: Container(us = 1); Container(const T&); ~Container(void){} us push_back(const T& = T()); us push_front(const T& = T()); us count(void) const; bool remove(us); const T& operator [](us) const; void set(const T&, us = 0); Container<T>& operator =(const Container<T>&); void save(ofstream& file); private: T* speicher; us length; }; #include "Container_Methoden.h" #endifBitte nicht schimpfen, falls irgendwas nicht passt...wie gesagt, konnte ich noch nicht testen.
Jetzt beschwert er sich über den Identifier ofstream, obwohl ich <fstream>
inkludiert habe.
Langsam, aber sicher kenn ich mich überhaupt nicht mehr aus.
-
Hat denn keiner eine Idee, was der Fehler sein sollte? Von mir aus könnte ich auch den ganzen Code posten, aber ich glaube nicht, dass das etwas helfen würde.
-
2und40 schrieb:
Hat denn keiner eine Idee, was der Fehler sein sollte? Von mir aus könnte ich auch den ganzen Code posten, aber ich glaube nicht, dass das etwas helfen würde.
niemand hier benutzt die glaskugel für so was. die argumentation ist auch fehlerhaft: da du die ursache nicht kennst, kannst du nicht wissen ob der nicht gepostete code nicht doch die ursache ist - und wenn wir schon davon ausgehen, das es kein compilerbug ist, dann muss sich das problem ja irgendwo dort finden lassen. das minimum wäre doch der code aller funktionen, die in diesem beispiel instantiiert werden. was probleme mit unbekannten bezeichnern betrifft: in dem code, den du gezeigt hast, hast du eben nicht <fstream> eingebunden - und da ostream kein abhängiger bezeichner ist, muss er bereits bei der deklaration bekannt. außerdem befindet sich ostream im namespace std...
aber wie gesagt: ohne den minimalen code zum compilieren ist sowieso alles nur rätselraten.
-
Hast natürlich Recht mit std.
Hier der Code:
template<class T> Container<T>::Container(us l) : length(l) { speicher = new T[l]; for(us = a; a < l; a++) { speicher[a] = T(); } } template<class T> Container<T>::Container(const T& quelle) { (*this) = quelle; // Zuweisungsoperator vorausgesetzt! } template<class T> us Container<T>::push_back(const T& quelle) { T* buffer = new T[length]; for(us a = 0; a < length; a++) buffer[a] = speicher[a]; delete[] speicher; speicher = new T[length + 1]; for(a = 0; a < length; a++) speicher[a] = buffer[a]; speicher[a] = quelle; ++length; delete[] buffer; return length; } template<class T> us Container<T>::push_front(const T& quelle = T()) { T* buffer = new T[length]; for(us a = 0; a < length; a++) buffer[a] = speicher[a]; delete[] speicher; speicher = new T[length + 1]; *speicher = quelle; for(a = 1; a < length + 1; a++) speicher[a] = buffer[a]; ++length; delete[] buffer; return length; } template<class T> bool Container<T>::remove(us d) { T* buffer = new T[length]; for(us a = 0; a < length; a++) buffer[a] = speicher[a]; delete[] speicher; speicher = new T[length - 1]; for(a = 0; a < d; a++) speicher[a] = buffer[a]; a++; for(; a < length; a++) speicher[a] = buffer[a]; --length; delete[] buffer; return true; } template<class T> us Container<T>::count(void) const { return length; } template<class T> const T& Container<T>::operator [](us a) const { if(a < length && a >= 0) return speicher[a]; return speicher[a]; } template<class T> void Container<T>::set(const T& quelle, us a) { speicher[a] = quelle; } template<class T> Container<T>& Container<T>::operator =(const Container<T>& quelle) { for(us a = 0; a < length; a++) speicher[a] = quelle[a]; return (*this); } template<class T> void Container<T>::save(ofstream& file) { for(us a = 0; a < length; a++) file << speicher[a]; }
-
template<class T> Container<T>::Container(const T& quelle) { (*this) = quelle; // Zuweisungsoperator vorausgesetzt! }nett - gemeint ist siche Container<T>::Container(const Container&)

so jedenfalls ist das eine endlosrekursion - worüber dich ein guter compiler auch informiert. im übrigen ist die implementation von copy-konstruktion durch copy-zuweisung semantisch fehlerhaft und extrem unschön. für gewöhnlich läßt das auf fehlendes verständnis für beide operationen schließen.
-
Was Copy-Konstruktor & Co machen sollen, ist mir schon klar.
Danke für den Hinweis, ich wollte hier die Elemente von einem Container nach *this mit dem Zuweisungsoperator kopieren (oder ist das auch irgendwie unsauber?); keine Ahnung, warum ich das so geschrieben habe.
Werds gleich mal ausbessern.
-
g++

-
2und40 schrieb:
Was Copy-Konstruktor & Co machen sollen, ist mir schon klar.
Danke für den Hinweis, ich wollte hier die Elemente von einem Container nach *this mit dem Zuweisungsoperator kopieren (oder ist das auch irgendwie unsauber?); keine Ahnung, warum ich das so geschrieben habe.
Werds gleich mal ausbessern.copy-zuweisung setzt ein fertig konstruiertes objekt voraus. prinzipiell muss also der vorherige zustand des objekts zerstört werden, bevor das objekt neu initialisiert wird - andernfalls gibt es ein resourcenleck. und hier ist das problem - damit der operator im konstruktor aufrufen werden kann, muss dieser konstruktor zumindest eine minimalinitialisierung durchführen - andernfalls zerstört der operator basierend auf nichtinitialisierten speicher, was undefiniertes verahlten ist. und das ist, wenn schon nichts anderes, extrem ineffizient. eine implementierung der zuweisung mittels copy-ctor ist ohne weiters möglich (z.b. per copy&swap) - der umgekehrte weg ist sehr fragwürdig und nie vorteilhaft.
P.S. dein zuweisungsop funktioniert im übrigen auch nicht wenn das argument einen andere größe hat.
-
Und noch ein Hinweis: Für die ganzen insert- und remove-Funktionen machst du dir unnötig Arbeit. Da reicht es aus, wenn du die Daten einmal kopierst:
us push_back(const T& val) { T* buffer = new T[length+1]; for(int i=0;i<length;++i) buffer[i]=speicher[i]; buffer[length]=val; delete[]speicher; speicher=buffer; return ++length; }(und von der Performance ist es noch besser, wenn du von vornherein mehr Platz reservierst als du im Moment benötigst (nimm dir ein Beispiel an vector<>)
-
Vielen Dank an alle, die mir geholfen haben, inzwischen läuft es.
Keine Ahnung, wieso es so ist, aber anscheinend war der fehlerhafte Copy-Konstruktor die Fehlerquelle, nachdem ich den umgeschrieben habe, hat die Ausgabe funktioniert.
Wenn mir jetzt noch jemand einen Tipp geben könnte, wie der Copy-Konstruktor mit der Ausgabe zusammenhängt, wäre ich vollkommen glücklich...
-
das war kein copy-konstruktor. und da sich dieser konstruktor rekursiv aufrief, ist dein program mit einem stack overflow ausgestiegen - der programmfluß hat den ausgabe ausdruck nie erreicht..
ausführlich:
der konstruktor nahm eine referenz auf konstantes T - für deine instanz also int. damit passt dieser konstruktor besser auf das argument in main() als derjenige, der ein unsigned short nimmt. der andere konstruktor wird also nie aufgerufen (andernfalls hätte sich dein compiler auch über den syntaxfehler darin beschwert).
-
Was auch der Grund ist, warum man beim Debuggen auf alle Optimierungen verzichten sollte.
Der Compiler optimiert nämlich in diesem Fall auch fehlerhaften Code "heraus" (z.B. weil er nie aufgerufen wird) und die Fehler bleiben dann aus.