Fragen zu einer getrennten Implementierung mit einer header-Datei



  • 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);
    
    };
    
    #endif
    

    Implementierungs-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	59
    

    Edit: Vorsicht: Die Zeilenangaben des Fehlertextes müssen nicht mit den Zeilenangaben des Codes hier im Forum übereinstimmen!


  • Mod

    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.	21
    

    Wie 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?


  • Mod

    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


Anmelden zum Antworten