iostream treibt mich noch in den Wahnsinn ...
-
Ich habe eine Templateklasse erstellt, welche Schwierigkeiten mit den istream- und ostream-Klassen hat:
#include <iostream> template <typename T> class CMyClass { public: #ifdef _IOSTREAM_ friend std::ostream& operator<< (std::ostream&,CMyClass<T>&); // Friend-Deklarationen für den vollen Zugriff friend std::istream& operator>> (std::istream&,CMyClass<T>&); #endif (...) }; #ifdef _IOSTREAM_ template <typename T> std::ostream& operator<< (std::ostream &out,CMyClass<T> &Obj) {(...)} template <typename T> std::istream& operator>> (std::istream &in ,CMyClass<T> &Obj) {(...)} #endif typedef CMyClass<int> CInt; typedef CMyClass<char> CChar; typedef CMyClass<double> CDouble; int main() { CInt nMyInt; CChar cMyChar; CDouble dMyDouble; ////////////////////////////////////////////////// // Bis hierhin läuft alles noch wie geschmiert ... ////////////////////////////////////////////////// std::cout<<"Geben sie eine Ganzzahl ein:\t"; std::cin >>nMyInt; std::cout<<"Geben sie einen Buchstaben ein:\t"; std::cin >>cMyChar; std::cout<<"Geben sie eine Dezimalzahl ein:\t"; std::cin >>dMyDouble; ////////////////////////////////////////////////// // ... doch beim Linken sagt das Programm, es gäbe // nicht aufgelöste externe Verweise, kurz: // Funktionsdefinition fehlen. Tun sie aber nicht, // die Klasse existiert und somit auch die Operatoren ////////////////////////////////////////////////// std::cout<<"Sie haben eingegeben:\n"; ////////////////////////////////////////////////// // Ebenso hier. Mein Compiler muss wohl die // Definitionen der Friend-Deklarationen nicht // erkennen. ////////////////////////////////////////////////// std::cout<<nMyInt; std::cout<<cMyChar; std::cout<<dMyDouble; return 0; }Ich überlade in meiner Klasse die Operatoren für Ein- und Ausgabe und definiere sie auch, aber mein Compiler erkennt nur die Deklarationen und verbindet sich nicht mit den Definitionen.
Ich habe schon ein bisschen rumexperimentiert und habe herausgefunden, dass dieses Problem NICHT auftaucht, wenn ich die Deklarationen in der Klasse auskommentiere. DANN scheint der Compiler die Definitionen als gültige Funktionen anzusehen und linkt ohne Probleme. Dies hat jedoch den Preis, dass ich nur öffentliche Memberfunktionen aufrufen kann.
Anscheinend versucht der Compiler, wenn die Funktionen IN DER KLASSE deklariert sind, diese Aufzurufen und dabei die Definitionen ausser Acht zu lassen. Daher der Fehler. Aber was kann ich tun, damit die Definition mit den Deklarationen verknüpft werden?
-
Hallo,
Vielleicht hilft dir ja das hier.
http://www.ica1.uni-stuttgart.de/Courses_and_Lectures/C++/script/node23.html#SECTION00531000000000000000
-
Danke, ich werde das gleich mal ausprobieren.
Ausserdem hätte ich noch ein Anliegen: Ich programmiere jetzt seit einem Jahr mit C++, habe aber keinen blassen Schimmer, wie Listen funktionieren. Nicht falsch verstehen, ich beherrsche Templates, Mehrfachvererbung und Zeigerarithmetik, sogar die MFC habe ich ein bisschen drauf, aber bei Listen steht mir das Hirn still. Jedes Mal, wenn ich mir Kapitel um Kapitel aus Büchern was zusammenreimen will, muss ich denken "Das ist sinnlos ... das kriege ich auch mit Zeigern hin ... " usw. Deshalb wollte ich fragen, ob Listen eurer Meinung nach wichtig sind oder nur ein Konzept zur Erleichterung der Programmierarbeiten. Und wenn sie wichtig sind, kann mir jemand ein gutes Tutorial oder Buch empfehlen, mit dem man Listen, verkettete Listen und Bäume erstellen lernt (da ich wirklich keinen blassen Schimmer habe, wozu das gut sein soll)?
-
Der aus dem Westen ... schrieb:
"Das ist sinnlos ... das kriege ich auch mit Zeigern hin ... "
Genau das ist der Sinn! Die Listen funktionieren (meistens) intern mit Zeigern, aber DU musst das eben nicht mehr selber machen und machst deshalb auch nicht mehr so leicht Fehler.
Zum Buch: Wenn du Templates, Zeiger usw. beherrscht, solltest du eigentlich kein Buch mehr nötig haben, um Listen zu verstehen und selber zu schreiben.
-
Eben doch. Ich meine, ich bin kein Guru, was C++ angeht, und ich beherrsche es erst seit einem Jahr. Aber mit Zeigern hatte ich (komischerweise, da viele Leute sagen, dass diese für Neulinge kompliziert seien) nie Probleme, was daran liegen könnte, dass ich mal eine Klasse, die nur auf Zeigern basierte, mit 6000 Zeilen Code ausgestattet habe und hinterher keinerlei Exception oder Speicherleck hatte.
Trotzdem bin ich eine Niete, wenn es um Listen geht. OK, ich habe mich mal getsern drangesetzt und habe versucht, ein Programm zu schreiben, in dem der Benutzer Knoten löschen und hinzugügen kann. Geht auch einigermassen (auch wenn es noch mit der Reihenfolge der auszugebenden Werten hapert), aber ich bin nicht zufrieden mit mir selbst. Glaubst du wirklich, wenn man Zeiger beherrscht, braucht man keine Listen mehr?
-
Der aus dem Westen ... schrieb:
Glaubst du wirklich, wenn man Zeiger beherrscht, braucht man keine Listen mehr?
Listen werden mittels Zeigern implementiert. Sie sind eine konkrete Anwendung von Zeigern.
Und ob du Listen brauchst oder nicht, hängt ganz davon ab, ob sie dir bei deinem Problem helfen: Listen kannst du problemlos auseinandernehmen, neu zusammenfügen, und überall schnell neue Elemente einfügen(allerdings in der Mitte mit Suchaufwand). Listen brauchst du also immer dann, wenn dein Problem am besten mit einer Liste gelöst werden kann.
Überlege dir also nochmal genau, was das Konzept hinter Zeigern ist, was Arrays sind, und vergleiche dies dann mit Listen und ihrer Aufgabe. Dann sollte sich dir der Sinn von Listen erschließen.
-
Der aus dem Westen ... schrieb:
[...] "Das ist sinnlos ... das kriege ich auch mit Zeigern hin ... " usw. Deshalb wollte ich fragen, ob Listen eurer Meinung nach wichtig sind oder nur ein Konzept zur Erleichterung der Programmierarbeiten.
Wieso "oder"? Die beiden Dinge schliessen sich nicht aus, im Gegenteil.
Unter anderem gerade weil verkettete Listen einem Arbeit abnehmen, einfache Benutzung ermöglichen und Fehler drastisch reduzieren, sind sie sehr wichtig. Listen als solche (die Datenstruktur selbst) hast du natürlich auch, wenn du das Ganze direkt mit Zeigern machst (also im Prinzip die Listenfunktionen jedes Mal wieder neu programmierst). Nur lohnt sich das nicht.
Für gewisse Einsatzgebiete eignen sich verkettete Listen besonders gut, wie schon von otze angetönt wurde. Zum Beispiel erfordern Einfügungen und Löschungen keine Verschiebung der anderen Elemente, was nicht nur schneller ist, sondern auch Zeiger, Referenzen und gegebenenfalls Iteratoren gültig bleiben lässt.