Fragen zu einer getrennten Implementierung mit einer header-Datei
-
#ifndef MYSTR_H // Makros schreibt man traditionell groß. Halte dich da dran, #define MYSTR_H // um die üblichen Makroprobleme zu vermeiden #include<iosfwd> // iostream ist zwar auch ok, aber iosfwd reicht, geht dann schneller zu compilieren. // #include<cstdlib> // Du benutzt keinen dieser beiden Header. Wozu also? // #include<string> // using namespace std; // using namespace in Headern. Eine Todsünde. class myStr { private: char *s; short laenge; public: myStr(); myStr(char *str); myStr(const myStr& str); ~myStr(); myStr operator = (myStr& str); // Wenn du den Operator als Klassenmember implementieren möchtest, // kann er kein friend sein. friend myStr operator + (myStr& str1, myStr& str2); friend std::ostream& operator << (std::ostream& o, myStr& x); }; #endif#include<iostream> // Dieses Mal brauchen wir den vollen iostream // #include<cstdlib> Benutzt du nicht #include<string> // Benutzt du nicht #include<cstring> // Benutzt du, hast du aber vergessen #include "myStr.h" using namespace std; // Hier ist das ok. myStr::myStr() { s = new char[1]; s[0] = '\0'; laenge = 0; } myStr::myStr(char *str) { laenge = strlen(str); s = new char[laenge+1]; strcpy(s,str); } myStr::myStr(const myStr& str) { laenge = str.laenge; s = new char[laenge+1]; strcpy(s,str.s); } myStr::~myStr() { delete s; } myStr myStr::operator = (myStr& str) // So schreibt man das { if(&str != this) { delete s; laenge = str.laenge; s = new char[laenge+1]; strcpy(s,str.s); } return *this; } myStr operator + (myStr& str1, myStr& str2) // Hier muss kein friend hin. Dies ist eine freie Funktion, die muss niemandem die Freundschaft erklären. { myStr str; str.laenge = str1.laenge + str2.laenge; str.s = new char [str.laenge+1]; strcpy(str.s, str1.s); strcat(str.s, str2.s); return str; } ostream& operator << (ostream& o, myStr& x) { return o << x.s; }Allgemein finde ich Kommentare lustig, die nochmal erläutern, was da schon steht. Fast wie:
++i; // Erhöht i um 1
-
Ich schreibe manchmal Kommentare, wenn ich mir selber klarmachen muss, was in dieser Zeile passiert. Ist wahrscheinlich so eine Anfängerangewohnheit.
-
Hi, du solltest die letzten drei Funktionen korrekt benennen:
myStr& myStr::operator = (myStr& str) { if(&str != this) { delete s; laenge = str.laenge; s = new char[laenge+1]; strcpy(s,str.s); } return *this; } friend myStr myStr::operator + (myStr& str1, myStr& str2) { myStr str; str.laenge = str1.laenge + str2.laenge; str.s = new char [str.laenge+1]; strcpy(str.s, str1.s); strcat(str.s, str2.s); return str; } friend ostream& myStr::operator << (ostream& o, myStr& x) { return o << x.s; }Gruß
Scarabol
-
kauflummi schrieb:
Ich schreibe manchmal Kommentare, wenn ich mir selber klarmachen muss, was in dieser Zeile passiert. Ist wahrscheinlich so eine Anfängerangewohnheit.
jain, kommentieren ist eine kunst für sich. ihr wisst ja: kommentare sind wie ein kurzer rock bei frauen -> sie sollen kurz sein, damit man keine angst davor hat, aber sie müssen lang genug sein, dass sie überhaupt sinnvoll sind
also ich ertappe mich auch immer wieder dabei, wie ich offensichtliche dinge nochmal in einem pseudo englisch denglisch dahinter tippe. ist in den fällen total unnötig. aber umgekehrt ists auch zu overkill wenn man einen gesamten algorithmus mit herleitung als kommentar reinhaut
zum problem: entferne das friend bei der implementierung
-
Scarabol schrieb:
Hi, du solltest die letzten drei Funktionen korrekt benennen:
myStr& myStr::operator = (myStr& str) { if(&str != this) { delete s; laenge = str.laenge; s = new char[laenge+1]; strcpy(s,str.s); } return *this; } friend myStr myStr::operator + (myStr& str1, myStr& str2) { myStr str; str.laenge = str1.laenge + str2.laenge; str.s = new char [str.laenge+1]; strcpy(str.s, str1.s); strcat(str.s, str2.s); return str; } friend ostream& myStr::operator << (ostream& o, myStr& x) { return o << x.s; }Gruß
ScarabolDie letzten beiden sind falsch.
-
So, erstmal Danke für eure zahlreichen Antworten! Ich hab jetzt mal die Änderungen durchgeführt, die SeppJ vorgeschlagen hat. Leider funktioniert's immer noch nicht ganz. Ich würde dich dich deshalb bitten nochmal kurz drüber zuschaun.
Was ich an der getrennten Implementation einer Klasse noch nicht ganz verstehe ist, wie man mit als friend deklarierte Funktionen umgeht. Hierzu schweigt sich leider mein Tutorial/Buch/Vorlesung total darüber aus und das Internet gibt auch nicht so viel dazu her.
Die überaldenen Operatoren =, + und << sollen übrigens nich nur als Methoden zur Verfügung stehen sondern als "richtige Funktionen"; mir fällt grad leider nicht besser ein wie man das bezeichnet.
Hier nochmal der Code:
header-Datei:
#ifndef MYSTR_H #define MYSTR_H #include<iostream> class myStr { private: char *s; //Zeiger, weil nun nun nicht mehr feste Größe! short laenge; public: myStr(); //allgemeiner Konstruktor myStr(char *str); //Zeichenkettenkonstruktor myStr(const myStr& str); //Copy-Konstruktor ~myStr(); //Destruktor myStr operator = (myStr& str); friend myStr operator + (myStr& str1, myStr& str2); friend std::ostream& operator << (std::ostream& o, myStr& x); }; #endifImplementierungs-Date:
#include<iostream> #include<string> #include "myStr.h" using namespace std; myStr::myStr() //allgemeiner Konstruktor { s = new char[1]; s[0] = '\0'; laenge = 0; } myStr::myStr(char *str) //Zeichenkettenkonstruktor { laenge = strlen(str); s = new char[laenge+1]; strcpy(s,str); } myStr::myStr(const myStr& str) //Copy-Konstruktor { laenge = str.laenge; s = new char[laenge+1]; strcpy(s,str.s); } myStr::~myStr() //Destruktor { delete s; } myStr myStr::operator = (myStr& str) { if(&str != this) { delete s; laenge = str.laenge; s = new char[laenge+1]; strcpy(s,str.s); } return *this; } myStr operator + (myStr& str1, myStr& str2) { myStr str; str.laenge = str1.laenge + str2.laenge; str.s = new char [str.laenge+1]; strcpy(str.s, str1.s); strcat(str.s, str2.s); return str; } ostream& operator << (ostream& o, myStr& x) { return o << x.s; }Fehlertext des compilers:
Fehler 6 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_main" in Funktion "___tmainCRTStartup". C:\Users\Tobias Mehrl\Desktop\test\test\MSVCRTD.lib(crtexe.obj) Fehler 7 error LNK1120: 1 nicht aufgelöste externe Verweise. C:\Users\Tobias Mehrl\Desktop\test\Debug\test.exe 1 Warnung 1 warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\users\tobias mehrl\desktop\test\test\mystr.cpp 21 Warnung 2 warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\users\tobias mehrl\desktop\test\test\mystr.cpp 29 Warnung 3 warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\users\tobias mehrl\desktop\test\test\mystr.cpp 46 Warnung 4 warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\users\tobias mehrl\desktop\test\test\mystr.cpp 58 Warnung 5 warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\users\tobias mehrl\desktop\test\test\mystr.cpp 59Edit: Vorsicht: Die Zeilenangaben des Fehlertextes müssen nicht mit den Zeilenangaben des Codes hier im Forum übereinstimmen!
-
Und? Funktioniert doch. Du kannst natürlich kein ausführbares Programm daraus machen, wenn es keine main-Funktion gibt.
-
Ich habe gerade bemerkt, dass es fehlerfrei kompiliert wenn ich in der main.cpp noch die main-Funktion reinschreibe.
Jetzt hab ich noch einige Fragen:
-> Warum brauch ich in der h-Datei für die letzte Überladung den Bezugsrahmenoperator "std::"?
-> Die Überladung des "="-Operators möchte ich auch als friend gestalten. Warum genügt es nicht einfach vor die Zeile ein "friend" zu setzen? Wenn ich das mache fällt mir in der myStr.cpp die überladene Funktion mit dem "=" mit dem compiler-Fehler "Fehler 2 error C2511: 'myStr myStr::operator =(myStr &)': Überladene Memberfunktion nicht in 'myStr' gefunden c:\users\tobias mehrl\desktop\test\test\mystr.cpp 40" aus.
Warum geht das nicht so einfach?
-
1. Weil du kein using namespace std; o.ä. im Header hast und das ist auch gut so.
2. Weil durch das friend der Operator keine Memberfunktion mehr ist und du das myStr:: in der Implementierungsdatei davor dadurch weglassen musst. Du solltest den Zuweisungsoperator jedoch so lassen, aus vielen guten Gründen.
-
Die 1. Antwort von dir hab ich verstanden, bei der 2. Antwort komm ich leider nicht mit.
Zur 2. Frage:
Gerade weil ich in der "="-Funktion das friend in der h-Datei weglassen musste (laut SeppJ), hab ich aber in der Implementierungsdatei das myStr:: hinzufügen müssen!
Mir ist nur nicht klar warum ich gerade die "="-Funktion in der h-Datei NICHT als friend deklarieren darf...
-
Mir is jetzt noch was aufgefallen:
Ich hab am obigen letzten Code von mir nichts mehr verändert. Wenn ich kompiliere, bekomme ich aber 5 Warnings der gleichen Sorte, die sich alle auf das strcpy() aus der Implementierungsdatei beziehen. Hier der Fehlertext:
Warnung 1 warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 21Wie bring ich noch die Warnings weg? Was soll an dieser funktion unsicher sein? Kann mit der Fehlermeldung nicht so wirklich was anfangen

Könnt ihr mir nochmals helfen?
-
Ja, nu, was soll man da noch erklären, was da nicht schon steht? Da strcpy stur arbeitet bis es die Nullterminierung findet, könnte der Kopiervorgang mehr (oder weniger) kopieren als gewollt ist, falls vorher schlampig gearbeitet wurde und die Nullterminierung vergessen wurde (oder an der falschen Stelle steht oder von einem bösen Hacker überschrieben wurde oder ...).
-
Da gibt es schon einiges zu zu sagen. Microsoft spielt sich als Papa auf und will einen dazu bringen, die eigenen, "sicheren" Ersatzfunktionen zu verwenden. Wenn man sich mit diesem Ziel identifizieren kann und auf Portabilität pfeift, macht man das. Ansonsten will man die Warnung weghaben. => See online help.
-
Soll das halso heißen, dass man die Warnings hier dann nicht mehr wegbekommt?
-
und stattdessen sollst du drüber nachdenken lieber strcpy_s zu verwenden, steht da aber auch.
zu deinem problem: der = operator ist ein teil deiner klasse, und der gehört nicht global als funktion implementiert (geht das eigentlich? hört sich schon so an als ob es geht). und im moment ist er als memberfunktion geschrieben, wie es sich auch gehört. und weil dieser ja schon teil deiner klasse ist, brauchst du kein friend, denn wieso willst du einen freund in deine familie lassen, obwohl er schon teil der familie ist?!
so fällt das friend weg, und das myStr:: muss dahin weil er eben schon zur klasse gehört