C++ anfängerfrage operator überladen

striker159

Lt. Junior Grade
Registriert
Dez. 2008
Beiträge
327
hallo

ich habe mir gerade eine ganz einfache klasse mit einer objektvariablen geschrieben.
nun will ich den operator += überladen, um die objektvariable um einen wert zu erhöhen.
hab etwas probiert, aber das kompiliert er leider garnciht erst. kann mir da jemand weiterhelfen, wie man das richtig macht?

Code:
using namespace std;

class Test{
	public:
		Test();
		double geta() const;
		friend Test operator+=(double d);

	private:
		double a;
};
Code:
#include <iostream>
#include "Test.h"

Test::Test(){
	a = 0.0;
}

double Test::geta() const{
	return a;
}

Test Test::operator+=(double d){
	if (d>0)
		this->a += d;
	return *this;	
}

// test
int main(){

}
 
compilermeldung lautet:

In file included from Test.cpp:2:0:
Test.h:7:34: error: 'Test operator+=(double)' must have an argument of class or enumerated type
Test.cpp:12:31: error: no 'Test Test::operator+=(double)' member function declared in class 'Test'
 
Code:
class Test
{
public:
	Test();
	double geta() const;
	
	// Operator +=, -=, /= usw. sind keine friends, sondern einfach nur Methoden. Ausserdem sollten sie eine Referenz auf *this zurückgeben.
	Test& operator += ( double d);
	 
private:
	double a;
};

Test& Test::operator += ( double d)
{
	a += d;
	return *this;
}
 
danke schonmal, jetzt wird es kompiliert.jedoch funktioniert es nur zum teil, es klappt nicht, wenn ich direkt += benutze.

Code:
int main(){
	Test* t = new Test();
	t->seta(5);
	cout << t->geta()<<endl;  // 5
	t->operator+= (10);
	cout << t->geta()<<endl;  // 15
	t += 5 ;
	cout << t->geta()<<endl;  // 0   <- Fehler ?	
	delete t;
}
 
stimmt :)

nochmal für mich zum verständis: (*t), weil nicht die adresse, auf die t zeigt, geändert werden soll, sondern das objekt, auf das t zeigt ?
 
Genau. t ist ein Pointer, also eine Variable, in der eine Adresse steht. Nach
t += 5
steht da eine andere Adresse drin, grob gesagt die "5 Objekte weiter". Danach ist der Pointer natürlich ungültig, falls er nicht zufällig gerade auf ein Arrayelement zeigt, hinter dem noch hinreichend viele Elemente sich befinden.
Mit
t->geta()
greifst du dann auf Speicher zu, der nicht dir gehört und in dem irgendein Unsinn steht, meistens eben die 0.
 
Warum legst du deine Test-Instanz überhaupt mit new an? Leg sie doch einfach auf den Stack.

Code:
int main(){
	Test t;
	t.seta(5);
	cout << t.geta()<<endl;  // 5
	t += 10;
	cout << t.>geta()<<endl;  // 15
	t += 5 ;
	cout << t.geta()<<endl;
}
 
antred schrieb:
Warum legst du deine Test-Instanz überhaupt mit new an? Leg sie doch einfach auf den Stack.

Warum sollte man sie denn nicht mit new anlegen, wenn man die Deallozierung nicht vergisst?

Einen definitiven Grund gibt es dort nicht wirklich, sogar eher was die Allozierung von weiterem Speicherplatz in den Objekten angeht.

Sehr einfaches Beispiel dazu die Frage auf SO:

http://stackoverflow.com/questions/...-its-memory/10366489#comment13359377_10366489
 
Keepers schrieb:
Warum sollte man sie denn nicht mit new anlegen, wenn man die Deallozierung nicht vergisst?

Weil es nicht nötig ist und man grundsätzlich nur dann auf dann auf den freestore zugreifen sollte, wenn es wirklich nötig ist?
 
Dann nenn mir mal EINEN guten Grund, weshalb du auf ein Objekt auf den Freestore legen würdest, wenn es dafür keine Notwendigkeit gibt.

Nachteile von Freestoreallozierungen:

  • Zu jedem new / new [] muß früher oder später das passende delete / delete [] folgen.
  • Freestore-Allozierung sind sehr laufzeitaufwändig und können in Multithreading-Programmen echte Performancekiller sein, da jedes new / delete einen globalen Mutex-lock involviert. Abhilfe können hier allerdings maßgeschneiderte Allokatoren oder Memorypools bringen.
  • Man muß mit Pointern rumeiern.
 
Die Problematik paralleler Programmierung (Mutex, Semaphoren, und andere Lösungswege zu Race Conditions und ungewolltem Verhalten) sollte in der Beziehung erstmal außer acht belassen werden.
Denn man programmiert "Same Program Multiple Data" grundsätzlich schon anders, inklusive Dinge die man dann beachten muss, als Single Program.

Das Rumeiern mit Pointern halte ich für ein "Anfänger" Problem. Früher oder später hat jeder damit den Dreh raus und hat keine Probleme mehr. Dann kriegt man es sogar hin übergreifende char** für einen execvp zB zu handhaben.

Das Argument der höheren Kosten für die Alloziierung stimmt voll und ganz. Da sehe ich auch kein Gegenargument.
Deshalb ist es das einzige Argument was ich bis jetzt zählen lasse, das aber die meisten einfach nicht nennen. Im Hinblick auf long-serving applications ist es auch "sicherer", aber auch dort habe ich schon oft Programme korrigieren müssen, die durch unsaubere Stack-Hantierung einen Stack-Overflow produziert haben, als durch das bewusst werden von "delete" beim Konsequenten anwenden von "new".

Im Grunde ist die Problematik dann also bei unsauberer Handhabung ähnlich, in der Praxis fehlt aber oft die awareness.. (Des passt schon ist ja kein Pointer).

Therefor habe ich da einfach immernoch eine andere Meinung dazu aus Erfahrung, und bin bis jetzt noch nicht überzeugt worden. Die Diskussionen können wir aber gerne per PM weiterführen :-)
 
Deswegen: http://www.youtube.com/watch?v=OB-bdWKwXsU&t=27m44s
new und delete sind übrigens 2 von 4 Operationen in C++, deren Laufzeit nicht bekannt ist, um den 2. Punkt von antred zu ergänzen.
Und zu 1.: Genau deswegen ist C++ verschrien als Sprache, deren Programme oft abstürzen. Wenn du so anfängst, dass es egal ist, wie man Sachen angeht, dann produzierst du früher oder später Speicherlecks. Warum mit Zeigern arbeiten, wenn der Stack keine Nachteile, aber Vorteile bei einem so einfache Beispiel hat. So einfach wie möglich halten...
 
Zuletzt bearbeitet:
Du hast mir aber immer noch keinen Grund genannt, weshalb du den freestore nutzen würdest, wenn's der Stack auch tut. ;)
Versteh mich nicht falsch - es gibt selbstverständlich jede Menge Situationen, in denen's der Stack eben NICHT tut und man zwangsweise zum freestore greifen muß, aber ich sprach ausdrücklich von solchen Fällen, in denen das nicht zutrifft.

aber auch dort habe ich schon oft Programme korrigieren müssen, die durch unsaubere Stack-Hantierung einen Stack-Overflow produziert haben, als durch das bewusst werden von "delete" beim Konsequenten anwenden von "new".

Und wie haben sie das geschafft? Durch Rumeiern mit Pointerarithmetik! ;)
 
Zurück
Oben