Operatorenüberladung



  • Hier lad das mal, hab ich mal für meine Klasse geschrieben:

    http://cache.sidewindershome.net/Operators.h

    MfG SideWinder



  • Der Operator ist Member der Klasse.

    Vielleicht stimmt ja mit der Verwendung des Operators etwas nicht. Die String-Klasse wird (unter anderem) für ein ebenfalls selbst geschriebenes assoziatives Array zur Identifikation verwendet. Die Methode zum Einfügen neuer Objekte in das Array stelle ich diese Methode zur Verfügung:

    void addObject(HLPStrings::String id, T object){...}
    

    Genau bei dieser Zeile meckert er. Die String-Klasse stellt folgende Member zur Verfügung:

    String();
    String(const String& s);
    String(const char* c);
    
    String& operator=(const String s);
    String& operator=(const String& s);
    String operator+(String& s);
    String& operator+=(String& s) ;
    bool operator==(const String& s2) const;
    bool operator!=(const String& s2) const;
    
    ~String();
    

    Ich würde sagen beim Aufruf von addObject müsste der String über den Copy-Konstruktor kopiert und über den Stack and die add-Methode übergeben werden.

    mfg



  • Aja, die Fehlermeldung wollte ich auch noch posten:
    undefined reference to `HLPStrings::String::operator=(HLPStrings::String const&) const'

    Und die Vergleichoperatoren sind nach der letzten Änderung natürlich keine Klassenmember mehr.

    mfg



  • String& operator=(const String s);
    String& operator=(const String& s);

    Wieso gibts hier zwei?

    MfG SideWinder



  • Es hat zuerst nur einen gegeben, aber weil es nicht funktioniert hat (gleicher Fehler) hab ich testweise den 2. hinzugefügt.

    mfg



  • Hmm, keine Ahnung...zeig mal die gesamte String-Klasse 😕

    Stilistische Änderung:

    void addObject(HLPStrings::String id, T object){...}
    // geändert zu:
    void addObject(const HLPStrings::String& id, T object){...}
    

    Verhindert, dass der String jedesmal kopiert werden muss wenn du ihn übergibst. Hilft beim konkreten Problem aber auch nix.

    MfG SideWinder



  • Ok, hier die gesamte String-Klasse. Sie befindet sich im Namespace HLPHelper und ist eine innere Klasse von HLPStrings.

    #include <HLPStrings.h>	// EH
    
    using namespace HLPHelper;
    
    // ========== class HLPStrings ==========
    
    // Returns the length of a native C string
    int32 HLPStrings::strLen(const char8* c){
    	int32 i = 0;
    	while (c[++i] != '\0');
    	return i;
    }
    
    // ========== class HLPStrings::String ==========
    
    // Compares this string with another one
    bool HLPStrings::String::operator==(const String& s2) const{
    	int32 strLen1 = HLPHelper::HLPStrings::strLen(this->getCString());
    	int32 strLen2 = HLPHelper::HLPStrings::strLen(s2.getCString());
    
    	// 2 strings with different lengths cannot be equal
    	if (strLen1 != strLen2) return false;
    
    	// Are all characters equal?
    	for (int32 i = 0; i < strLen1; i++)
    		if ((this->getCString())[i] != (s2.getCString())[i]) return false;
    
    	// The strings are equal
    	return true;
    }
    
    // Compares this string with another one
    bool HLPStrings::String::operator!=(const String& s2) const{
    	int32 strLen1 = HLPHelper::HLPStrings::strLen(this->getCString());
    	int32 strLen2 = HLPHelper::HLPStrings::strLen(s2.getCString());
    
    	// 2 strings with different lengths cannot be equal
    	if (strLen1 != strLen2) return true;
    
    	// Are all characters equal?
    	for (int32 i = 0; i < strLen1; i++)
    		if ((this->getCString())[i] != (s2.getCString())[i]) return true;
    
    	// The strings are equal
    	return false;
    }
    
    // Compares this string with another one
    bool operator==(const HLPHelper::HLPStrings::String& s1, const HLPHelper::HLPStrings::String& s2){
    	int32 strLen1 = HLPHelper::HLPStrings::strLen(s1.getCString());
    	int32 strLen2 = HLPHelper::HLPStrings::strLen(s2.getCString());
    
    	// 2 strings with different lengths cannot be equal
    	if (strLen1 != strLen2) return false;
    
    	// Are all characters equal?
    	for (int32 i = 0; i < strLen1; i++)
    		if ((s1.getCString())[i] != (s2.getCString())[i]) return false;
    
    	// The strings are equal
    	return true;
    }
    
    // Compares this string with another one
    bool operator!=(const HLPHelper::HLPStrings::String& s1, const HLPHelper::HLPStrings::String& s2){
    	int32 strLen1 = HLPHelper::HLPStrings::strLen(s1.getCString());
    	int32 strLen2 = HLPHelper::HLPStrings::strLen(s2.getCString());
    
    	// 2 strings with different lengths cannot be equal
    	if (strLen1 != strLen2) return true;
    
    	// Are all characters equal?
    	for (int32 i = 0; i < strLen1; i++)
    		if ((s1.getCString())[i] != (s2.getCString())[i]) return true;
    
    	// The strings are equal
    	return false;
    }
    
    // Constructor for the string class (copy constructor)
    HLPStrings::String::String(const String& s){
    	strLen = 0;
    	chars = 0;
    	if (s.getCString() != 0)
    		setString(s.getCString());
    }
    
    // Constructor for the string class
    HLPStrings::String::String(){
    	strLen = 0;
    	chars = 0;
    }
    
    // Constructor for the string class
    HLPStrings::String::String(const char8* c){
    	strLen = -1;
    	// Determine string length
    	while (true)
    		if (c[++strLen] == '\0') break;
    	// Copy string
    	chars = new char8[strLen + 1];
    	for (int32 i = 0; i < strLen; i++)
    		chars[i] = c[i];
    	chars[strLen] = '\0';
    }
    
    // Destructor: Removes the string from memory
    HLPStrings::String::~String(){
    	if (chars != 0)
    		delete []chars;
    	strLen = 0;
    }
    
    // Copies the string
    /*
    HLPStrings::String& HLPStrings::String::operator=(const String s){
    	if (s.getCString() != 0)
    		setString(s.getCString());
    	else
    		setString("");
    
    	return *this;
    }
    */
    
    // Copies the string
    HLPStrings::String& HLPStrings::String::operator=(const String& s){
    	if (s.getCString() != 0)
    		setString(s.getCString());
    	else
    		setString("");
    
    	return *this;
    }
    
    HLPStrings::String HLPStrings::String::operator+(String& s) {
    	// Create a new string
    	String newStr(this->getCString());
    	newStr.append(&s);	// Append the second string
    	return newStr;		// Return the new string
    }
    
    // Does the same as append does
    HLPStrings::String& HLPStrings::String::operator+=( String& s) {
    	append(&s);
    	return *this;
    }
    
    // Compares this string with another one
    bool HLPStrings::String::equals(String& s){
    	int32 strLen1 = this->getStrLen();
    	int32 strLen2 = s.getStrLen();
    
    	// 2 strings with different lengths can not be equal
    	if (strLen1 != strLen2) return false;
    
    	// Are all characters equal?
    	for (int32 i = 0; i < strLen1; i++)
    		if ((this->getCString())[i] != (s.getCString())[i]) return false;
    
    	// The strings are equal
    	return true;
    }
    
    // Sets another string into this one
    void HLPStrings::String::setString(String* s){
    	setString(s->getCString());
    }
    
    // Sets a C-string into this one
    void HLPStrings::String::setString(const char8* c){
    	// Delete old string (if necessary)
    	if (chars != 0)
    		delete []chars;
    	strLen = 0;
    	// Determine string length
    	if (c != 0){
    		while (true)
    			if (c[++strLen] == '\0') break;
    	}else{
    		strLen = 0;
    	}
    	chars = new char8[strLen + 1];
    	for (int32 i = 0; i < strLen; i++)
    		chars[i] = c[i];
    	chars[strLen] = '\0';
    }
    
    // Appends a string to the current one
    void HLPStrings::String::append(String* c){
    	append(c->getCString());
    }
    
    // Appends a character to the current string
    void HLPStrings::String::append(const char8 c){
    	char8 tmpStr[2];
    	tmpStr[0] = c;
    	tmpStr[1] = '\0';
    	append(tmpStr);
    }
    
    // Appends one C-string to the current string
    void HLPStrings::String::append(const char8* c){
    	int32 newStrLen = -1;
    	// Determine string length
    	while (true)
    		if (c[++newStrLen] == '\0') break;
    
    	// Create one new total string
    	char8* totalString = new char8[strLen + newStrLen + 1];
    	for (int32 i = 0; i < strLen; i++)		// Copy old part of the string into the new char8 array
    		totalString[i] = chars[i];
    	for (int32 i = 0; i < newStrLen; i++)		// Copy new part of the string into the new char8 array
    		totalString[strLen + i] = c[i];
    	strLen += newStrLen;
    	totalString[strLen] = '\0';
    
    	// Now, delete the old string and set the new one
    	delete []chars;
    	chars = totalString;
    }
    
    // Returns the length of the string
    int32 HLPStrings::String::getStrLen(){
    	return strLen;
    }
    
    // Returns the native C string
    const char8* HLPStrings::String::getCString() const{
    	return chars;
    }
    
    // Returns one character of the string
    char8 HLPStrings::String::getChar(int32 index){
    	if (index >= strLen)
    		return ' ';				// Out of bounds
    	else
    		return chars[index];
    }
    
    // Trims the current string
    // (Note: This function does not only remove blanks at the beginning and at the end but all blanks in
    //  the string)
    void HLPStrings::String::trim(){
    	HLPStrings::String s;
    	for (int32 i = 0; i < strLen; i++)
    		if (chars[i] != ' ') s.append(chars[i]);
    	setString(&s);
    }
    
    // This function replaces one char8 with another
    void HLPStrings::String::replace(char8 oldC, char8 newC){
    	for (int32 i = 0; i < strLen; i++)
    		if (chars[i] == oldC) chars[i] = newC;
    }
    
    // Returns if the current string can be converted into a double64 value
    // (Note: The convertion does never cause an error, but the result is not always useful).
    bool HLPStrings::String::isDouble(){
    	bool commaOccured = false;
    	for (int32 i = 0; i < strLen; i++){
    		switch(chars[i]){
    			case '+':
    			case '-':
    				// Only allowed at the beginning of the string
                    if (i > 0)
    					return false;
    				break;
    			case '.':
    			case ',':
    				// Only one such sign is allowed in a string
    				if (commaOccured == true)
    					return false;
    				commaOccured = true;
    				break;
    			case '0':
    			case '1':
    			case '2':
    			case '3':
    			case '4':
    			case '5':
    			case '6':
    			case '7':
    			case '8':
    			case '9':
    				break;
    			default:
    				// Other chars are not allowed
    				return false;
    				break;
    		}
    	}
    
    	return true;
    }
    
    // Converts the current string into a long64 number and returns it
    long64 HLPStrings::String::getLong(){
    	int32 sign = 1;		// 1 = +; -1 = -
    	long64 result = 0;
    	long64 digitValue;	// A temporary storage for the real value of one digit
    	for (int32 i = 0; i < strLen; i++){
    		switch(chars[i]){
    			case '+':
    				// Store sign
    				sign = 1;
    				break;
    			case '-':
    				// Store sign
    				sign = -1;
    				break;
    			case '0':
    			case '1':
    			case '2':
    			case '3':
    			case '4':
    			case '5':
    			case '6':
    			case '7':
    			case '8':
    			case '9':
    				digitValue = (chars[i] - '0');
    				result *= 10;
    				result += digitValue;
    				break;
    			default:
    				break;
    		}
    	}
    	// Process sign
    	result *= sign;
    
    	return result;
    }
    
    // Converts the current string into a double64 number and returns it
    double64 HLPStrings::String::getDouble(){
    	int32 sign = 1;		// 1 = +; -1 = -
    	bool comma = false;	// Process the digits after the comma (true) or before the comma (false)?
    	int32 commaCount = 0;
    	double64 result = 0.0;
    	double64 digitValue;	// A temporary storage for the real value of one digit
    	for (int32 i = 0; i < strLen; i++){
    		if (comma == true)
    			commaCount++;
    		switch(chars[i]){
    			case '+':
    				// Store sign
    				sign = 1;
    				break;
    			case '-':
    				// Store sign
    				sign = -1;
    				break;
    			case '.':
    			case ',':
    				// Start counting the digits after the comma
    				comma = true;
    				break;
    			case '0':
    			case '1':
    			case '2':
    			case '3':
    			case '4':
    			case '5':
    			case '6':
    			case '7':
    			case '8':
    			case '9':
    				// Process digit
    				if (comma == false){				// Before the comma
    					digitValue = (chars[i] - '0');
    					result *= 10;
    					result += digitValue;
    				}else{								// After the comma
    					digitValue = (chars[i] - '0');
    					// Now, divide the number by 10 as often as we have digits after the comma.
    					for (int32 i = 0; i < commaCount; i++)
    						digitValue /= 10;
    					result += digitValue;
    				}
    
    				break;
    			default:
    				break;
    		}
    	}
    	// Process sign
    	result *= sign;
    
    	return result;
    }
    
    // Converts the current string into a float32 number and returns it
    float32 HLPStrings::String::getFloat(){
    	int32 sign = 1;		// 1 = +; -1 = -
    	bool comma = false;	// Process the digits after the comma (true) or before the comma (false)?
    	int32 commaCount = 0;
    	float32 result = 0.0;
    	float32 digitValue;	// A temporary storage for the real value of one digit
    	for (int32 i = 0; i < strLen; i++){
    		if (comma == true)
    			commaCount++;
    		switch(chars[i]){
    			case '+':
    				// Store sign
    				sign = 1;
    				break;
    			case '-':
    				// Store sign
    				sign = -1;
    				break;
    			case '.':
    			case ',':
    				// Start counting the digits after the comma
    				comma = true;
    				break;
    			case '0':
    			case '1':
    			case '2':
    			case '3':
    			case '4':
    			case '5':
    			case '6':
    			case '7':
    			case '8':
    			case '9':
    				// Process digit
    				if (comma == false){				// Before the comma
    					digitValue = (float32)(int32)(chars[i] - '0');
    					result *= 10;
    					result += digitValue;
    				}else{								// After the comma
    					digitValue = (float32)(int32)(chars[i] - '0');
    					// Now, divide the number by 10 as often as we have digits after the comma.
    					for (int32 i = 0; i < commaCount; i++)
    						digitValue /= 10;
    					result += digitValue;
    				}
    
    				break;
    			default:
    				break;
    		}
    	}
    	// Process sign
    	result *= sign;
    
    	return result;
    }
    
    // Converts a double64 value into a string and sets this string
    void HLPStrings::String::setDouble(double64 d){
    	// Create a character array which is long64 enough in all cases
    	char8 tmpStringBuffer[30];	// A maximum of 30 digits is supported
    	int32 charIndex = 0;			// Points to the character which is written now
    	// First of all, write the sign into the string
    	if (d < 0){
    		tmpStringBuffer[charIndex++] = '-';
    		d = -d;	// Remove the sign from the double64 value
    	}
    
    	// Extract two different long64 values: before and after the comma
    	long64 bComma = (long64)d;
    	double64 tmpD = (d - (double64)bComma);
    	for (int32 i = 0; i < 8; i++)	// Convert a maximum of 8 digits after the comma
    		tmpD *= 10;
    	long64 aComma = (long64)tmpD;
    	int32 oldCharIndex;
    	int32 tmp;
    
    	// Now, convert the part before the comma
    	oldCharIndex = charIndex;
    	while (bComma > 0){
    		tmpStringBuffer[charIndex++] = '0' + (uchar8)(bComma % 10);
    		bComma /= 10;
    	}
    	// Reverse the string from oldCharIndex until charIndex
    	for (int32 i = 0; i < (charIndex - oldCharIndex) / 2; i++){
    		tmp = tmpStringBuffer[charIndex - 1 - i];
    		tmpStringBuffer[charIndex - 1 - i] = tmpStringBuffer[oldCharIndex + i];
    		tmpStringBuffer[oldCharIndex + i] = tmp;
    	}
    
    	// Check if the number has digits after the comma
    	if (aComma > 0){
    		// Add the comma
    		tmpStringBuffer[charIndex++] = '.';
    
    		// Now, convert the part before the comma
    		oldCharIndex = charIndex;
    		while (aComma > 0){
    			tmpStringBuffer[charIndex++] = '0' + (uchar8)(aComma % 10);
    			aComma /= 10;
    		}
    		// Reverse the string from oldCharIndex until charIndex
    		for (int32 i = 0; i < (charIndex - oldCharIndex) / 2; i++){
    			tmp = tmpStringBuffer[charIndex - 1 - i];
    			tmpStringBuffer[charIndex - 1 - i] = tmpStringBuffer[oldCharIndex + i];
    			tmpStringBuffer[oldCharIndex + i] = tmp;
    		}
    		tmpStringBuffer[charIndex] = '\0';
    		// Check if we can move the \0 to the beginning of the string. This is possible if the last
    		// digit (after the comma) is 0
    		while (tmpStringBuffer[charIndex - 1] == '0'){
    			charIndex--;
    			tmpStringBuffer[charIndex] = '\0';
    		}
    	}else{
    		tmpStringBuffer[charIndex] = '\0';
    	}
    
    	// Now, use the generated string
    	setString(tmpStringBuffer);
    }
    


  • Ich meinte die Header-Datei 🙄

    BTW: Die aktuelle bitte, hier sind ja die OPs noch Member, etc. 😉

    MfG SideWinder



  • Achso, den header 😉

    namespace HLPHelper{
    
    	class HLPStrings{
    	private:
    
    	public:
    		static int32 strLen(const char8* c);
    
    		// String control class
    		class String{
    		private:
    			char8* chars;
    			int32 strLen;
    		public:
    			String();
    			String(const String& s);
    			String(const char8* c);
    			void append(String* c);
    			void append(const char8* c);
    			void append(const char8 c);
    			void setString(String* s);
    			void setString(const char8* c);
    			HLPStrings::String& operator=(const String s);
    			HLPStrings::String& operator=(const String& s);
    			HLPStrings::String operator+(String& s);
    			HLPStrings::String& operator+=(String& s) ;
    			friend bool operator==(const String& s1, const String& s2);
    			friend bool operator!=(const String& s1, const String& s2);
    			bool String::equals(String& s);
    			const char8* getCString() const;
    			int32 getStrLen();
    			char8 getChar(int32 index);
    			void trim();
    			bool isDouble();
    			long64 getLong();
    			double64 getDouble();
    			float32 getFloat();
    			void setDouble(double64 d);
    			void replace(char8 oldC, char8 newC);
    
    			~String();
    		};
    
    	};
    
    }
    
    bool operator==(const HLPHelper::HLPStrings::String& s1, const HLPHelper::HLPStrings::String& s2);
    bool operator!=(const HLPHelper::HLPStrings::String& s1, const HLPHelper::HLPStrings::String& s2);
    

    mfg



  • ChrisR schrieb:

    Aja, die Fehlermeldung wollte ich auch noch posten:
    undefined reference to `HLPStrings::String::operator=(HLPStrings::String const&) const'

    Du rufst op= für ein konstantes Objekt auf, was nicht funktionieren kann. Zeig mal die Zeile, in der der Fehler auftritt.

    btw:
    Du hast enorme Probleme mit const-correctness. Schnapp dir ein gutes Tutorial, in dem erklärt wird, wann Methoden bzw. Operatoren const gemacht werden und arbeite daran.



  • @groovemaster: Die wurde doch schon gepostet, siehe weiter oben die Funktion. Deswegen kann dein Schluss auch nciht richtig sein. Hab ich mir auch schon gedacht.

    @ChrisR: Ganz allgemein ist die Klasse nicht das Optimum, die wichtigsten Probleme:
    void append(String* c); <- so nicht
    void setString(String* s); <- so nicht
    HLPStrings::String& operator=(const String s); <- den hier weg endlich
    bool String::equals(String& s); <- hier const String&

    Ansonsten kann ich aber nicht den Grund des Problems erkennen. Kanns sein, dass dein Compiler zwar auf die Funktion zeigt, das Problem aber nicht im Kopf stattfindet sondern irgendwo im Rumpf dieser Funktion? Was macht denn diese addObject?

    MfG SideWinder



  • SideWinder schrieb:

    Die wurde doch schon gepostet

    Was? Die Fehlerstelle? Zeig mal wo, bin gerade zu faul, erst den ganzen Code durchzuschaun. 🙂



  • omg, bist du faul 😃

    ChisR schrieb:

    void addObject(HLPStrings::String id, T object){...}
    

    Genau bei dieser Zeile meckert er.

    Vielleicht erkennst du ja den Fehler 😕

    MfG SideWinder



  • SideWinder schrieb:

    omg, bist du faul 😃

    Sind das nicht alle Programmierer? 😃

    ChisR schrieb:

    void addObject(HLPStrings::String id, T object){...}
    

    Genau bei dieser Zeile meckert er.

    So wird das nix. Man braucht schon den Aufruf bzw. die Definition von addObject, um den Fehler zu finden. Momentan kann ich hier jedenfalls keine Verwendung von op= erkennen.


Anmelden zum Antworten