P.roblem s.olved :)
-
Hier meine Lösung:
Feld.h
/* * Feld.h * * Created on: 16.09.2009 * Author: c.groupe */ #ifndef FELD_H_ #define FELD_H_ class Feld { double *f; int groesse; public: Feld (); // Konstruktor Feld (int g); // Konstruktor 2 double get (int index); void set (int index, double wert); virtual ~Feld(); // Destruktor }; #endifFeld.cpp
/* * Feld.cpp * * Created on: 16.09.2009 * Author: c.groupe */ #include "feld.h" #include <iostream> using namespace std; Feld::Feld() { groesse = 16; f = new double[groesse]; for (int i=0; i<groesse; ++i) f[i] = 0; } Feld::Feld(int g) { groesse = g; if (groesse > 0) { f = new double[groesse]; for (int i=0; i<groesse; ++i) f[i]=0; } else cout << "\nFehler: Feld zu klein!\n"; } double Feld::get(int index) { // Lesen einen Wertes if((index >= 0) && (index < groesse)) return f[index]; else { cerr << index << "\nFehler: Index Existiert nicht!\n"; exit(-1); } } void Feld::set( int index, double wert) { // Wert wird hier gesetzt if((index >= 0) && (index < groesse)) f[index] = wert; else { cerr << index << "\nFehler: Index Falsch!\n"; exit(-1); } } Feld::~Feld() { delete[] f; }main.cpp
/* * Main.cpp * * Created on: 14.09.2009 * Author: c.groupe */ #include "feld.h" #include <iostream> using namespace std; int main() { double i; Feld v1(12), v2; v1.set(2, 4.3); i = v1.get(2); cout << i << '\n'; return 0; }
-
Sieht ziemlich gut aus. Zwei Bemerkungen (Pukte 1 und 3) und einen Fehler (Punkt 2) habe ich:
- Man kann Funktionen Standardwerte mitgeben, die für den Fall genommen werden, dass kein Wert angegeben wird. Auf diese Weise kannst du dir den Fall wo kein Argument angegeben wird sparen. Man schreibt dies so:
Feld (int g=16);Feld::~Feld() { delete[] f; }Du hast richtig erkannt, dass du einen eigenen Destruktor für die Klasse brauchst. Aber überleg nochmal, was passiert, wenn ein Objekt der Klasse kopiert werden soll.
Kleiner Tipp: Es gibt für C++ eine Faustregel (die sogenannte Regel der großen Drei oder auch einfach Dreierregel), die besagt, dass eine Klasse die eine der folgenden Methoden benötigt, auch die anderen beiden benötigt:- Kopierkonstruktor
- Destruktor
- Zuweisungsoperator
Diese Regel trifft hier zu.
- Ich weiß nicht, ob es in deinem Buch schon vorgekommen ist: Es gibt auch vorzeichenlose Zahlentypen (unsigned int). Da negative Feldgrößen unsinnig sind könntest du diese benutzen.
"Feld zu klein!" ist wohl eher ein Fall für cerr als cout, wie die anderen Fehler auch.
-
Das sieht soweit ganz gut aus. Ich würde ein paar kleinere Sachen ändern:
-Als Typ für die größe würde ich unsigned int oder size_t nehmen, um anzuzeigen, dass es ein Vorzeichenloser Typ ist.
-Den Konstruktor würde ich so definieren
Feld( int g = 16 ) { }Das vermeidet Codedopplung und ist eine gängige Methode.
-Falls beim Konstruktor die Größe 0 übergeben wird, kannst du das eigentlich zulassen.
-die get Methode kannst du als konstante Methode implementieren
-und warum ist der Destruktor virtuell? Ist in dem Falle unnötig
-beim Setzen des feldes könntest du 0.0 satt 0 benutzen

-wenn du schon den Destruktor implementierst, warum dann nicht gleich auch noch den copy constructor?

-
Vielen Dank fürs drüber schauen!
@SeppJ, ok werd ich mir dann mal anschauen.
@sdfsdf, der grund liegt darin, dass ich kein perfektes programm schreiben will,
sondern einfach erst mal nur die geforderte aufgabe lösen
-
Ich würde
- den Konstruktor noch explizit machen, um zu verhindern, dass ein int implizit zu einem Feld konvertierbar wird.
- Kopieren und Zuweisung entweder erlauben und richtig implementiereun oder verbieten. In deinem Fall generiert der Compiler automatisch Kopier-Konstruktor und Zuweisungsoperator. Diese tun aber nicht das richtige. Siehe DreierregelDas, was du hier als "nicht perfekt" bezeichnest ist strenggenommen keine brauchbare Lösung. Zuweisung und Kopieren wird bei Dir erlaubt, geht aber nach hinten los. Also, schreibe entweder
// boost::noncopyable verhindert, dass der Compiler einen eigenen // Kopier-Konstruktor und Zuweisungoperator erzeugt. Die würden // nämlich das falsche machen (einfach den Zeiger kopieren) class Feld : boost::noncopyable { explicit Feld(int groesse = 16); ~Feld(); // Destruktor muss nicht virtual sein };(boost::noncopyable findest Du hier)
oderclass Feld { public: explicit Feld(int groesse = 16); Feld(Feld const&); // eigener Kopier-Konstruktor Feld& operator=(Feld const&); // eigener Zuweisungsoperator ~Feld(); // Destruktor muss nicht virtual sein };Gruß,
SP
-
dann kann er eigentlich im konstruktor auch mit der initialisierungsliste arbeiten
Feld(int g = 16) : f( (g>=0) ? new double[g] : NULL ), groesse(g) { if(!g)cerr<<"Fehler"; }