Eigene Klasse Vektor



  • Hallo,
    wo ich den Code gerade mal so überfliege, möchte ich doch noch mal an die Regel der Großen Drei erinnern. Hier passt sie mal wieder sowas von.



  • Hi,
    bei der Sache mit den friends muss ich dir Recht geben! Das "müssen" ist natürlich relativ! 😉
    Aber Die Regel der Großen Drei trifft hier wohl nicht zu: Ne flache Kopie tuts hier ja nicht!
    Ausserdem: Ich halte das hier für ein akademisches Beispiel zum Lernen von OOP mit C++ ... da soll man doch noch schön alles implementieren 😉



  • Sepp Brannigan schrieb:

    Aber Die Regel der Großen Drei trifft hier wohl nicht zu: Ne flache Kopie tuts hier ja nicht!

    genau, und weil es eine flache kopie nicht tut, greift die Regel der grossen Drei!

    denn was sagt diese regel uns:

    Wenn du tust Ctor, CopyCtor oder op= implementierst, wirst du auch die anderen beiden brauchen



  • oops ... mein Fehler ... das ist ein +=. Übersehen!
    Drum dacht ich, du meinst: Man könnte sich den ganzen Zirkus lt. den grossen drei sparen. Sorry
    Dann braucht man sicherlich das volle Programm. Aber hier fehlen sowiso noch ein paar Sachen, wie Tobias vielleicht noch feststellen wird. z.B. ein explicit vorm Ctor oder so ...



  • Hi!
    Danke für die Anregungen!

    Hab's mal umgesetzt:

    #include <iostream>
    
    using namespace std;
    
    class Vektor
    {
    		friend ostream &operator<<(ostream&, const Vektor&);
    
    	private:
    		const int dim;
    		int *komponenten;
    
    	public:
    		Vektor(int d) : dim(d) { komponenten = new int[dim]; }
    		Vektor(const Vektor&);
    		~Vektor();
    		int getDim() { return dim; }
    		int getVek(int);
    		void setVek(int, int);
    		Vektor &operator+=(const Vektor&);
    };
    
    Vektor::Vektor(const Vektor& other) : dim(other.dim)
    {
    	komponenten = new int[dim];
    	for(int i=0; i<dim; i++)
    		komponenten[i]=other.komponenten[i];
    }
    
    Vektor::~Vektor()
    {
    	delete[] komponenten;
    }
    
    int Vektor::getVek(int pos)
    {
    	return komponenten[pos];
    }
    
    void Vektor::setVek(int pos, int wert)
    {
    	komponenten[pos]=wert;
    }
    
    Vektor &Vektor::operator+=(const Vektor& other)
    {
    	for(int i=0; i<getDim(); i++)
    		komponenten[i]+=other.komponenten[i];
    
    	return (*this);
    }
    
    ostream &operator<<(ostream& ausgabe, const Vektor& other)
    {
    	ausgabe << "Vektor mit " << other.getDim() << " Komponenten:" << endl;
    	for(int i=0; i<other.getDim(); i++)
    		ausgabe << i << ". Komponente: " << other.getVek(i) << endl;
    
    	return ausgabe;
    }
    

    Laut Compiler macht nur noch die Ausgabe-Überladung Probleme. Vor allem die benutzten Methoden, aber warum?

    THX!



  • Hallo,

    sorry ... daran hat ich nicht gedacht.
    Da du in der Ausgabefunktion eine const Vector Referenz übernimmst, ist das Teil in der Funktion konstant und erlaubt dir nicht auf normale Methoden zuzugreifen - denn die könnten ja das Teil unbemerkt verändern. Deshalb wird gemeckert.
    Ausweg: Du musst die entsprechenden Methoden für const-Objekte freigeben. Sowas macht man per const-Angabe hinter den Parameterklammern:

    int getDim() const { return dim; } // würd ich übrigens inline machen
    // und
    int getVek(int) const;  // Deklaration
    int Vector::getVek(int pos) const { ... }
    

    das wars. Übrigens: Der Compiler prüft die const-Funktionen auf Schummeleien 😉

    viel Erfolg!



  • Ich bin über das Thema nur drübergeflogen, aber mir ist was vielleicht Wichtiges eingefallen... falls Du MS Visual C++ 6.0 verewendest gibt's da möglicherweise Probleme beim Überladen des stream-Operators (da bin ich nämlich mal fast dran verzweifelt).
    Du solltest in dem Fall dann mal den neusten Service Pack für's Visual Studion installieren (steht aber glaube ich in den FAQs).



  • Sepp Brannigan schrieb:

    int getDim() const { return dim; } // würd ich übrigens inline machen
    

    Ist es so auch schon.



  • operator void schrieb:

    Ist es so auch schon.

    echt? Bitte mehr Info! *lechz*



  • Sepp Brannigan schrieb:

    operator void schrieb:

    Ist es so auch schon.

    echt? Bitte mehr Info! *lechz*

    wird die funktion innerhalb der klasse definiert, ist sie automatisch inline.



  • aha ... ist mir wohl entgangen.



  • Danke für die vielen Tipps! 🙂

    Mal ne andere Frage:
    Wenn ich in einer Klasse einen Zeiger defiere und diesen per Konstruktor einem
    konstanten Zeiger zuweisen will, wie mache ich das?

    class Flugzeug
    {
    	private:
    		char *typ;
    		...
    	public:
    		Flugzeug(const char *t) : typ(t) {}
                      ...
    };
    

    So klappts nicht. Wie denn?

    THX
    Tobias



  • Du bekommst nen Zeiger auf konstanten Inhalt, weist den einem anderen - nicht const - zu und schon kannst nach Herzenslust rumschreiben... wär doch frech!
    Also entweder den Zeiger *char typ; als *const char typ; deklarieren, oder das const aus der Parameterliste des Konstruktors rausschmeissen. Das wär aber unpraktisch, da man dann keine Zeichenketten mehr direkt übergeben kann - also: Flugzeug("Boing 747"); würd dann nicht mehr gehen.

    Ausserdem: Hier ist nicht der Zeiger konstant, sondern der Inhalt.

    const char *const abc = "abc";
    

    Das const vor dem char bezieht sich auf den Inhalt. Das andere auf den Zeiger selbst. Ist ein feiner Unterschied.
    Aber wer die Wahl hat ... braucht für den Spott nicht zu sorgen - oder wie war das?



  • THX!

    Aber wenn ich char *typ nun auch const mache, speichere ich dann nicht nur den ersten Buchstaben des übergebenen Namens?

    OK -> Hat sich erledigt. My fault!

    Ciao & nochmals Danke!



  • Alles was du mit z.B. der Variable typ speichern kannst ist die Adresse eines Zeichens irgendwo im Speicher - mehr nicht! Möglicherweise ist dieses Zeichen das erste einer null-terminierten Zeichenkette. Falls du daran denkst eine Zeichenkette in einer Funktion zu übernehmen und dann typ zuzuweisen: Du weist nur die Adresse zu! Ich vermute mal, du willst die übergebene Zeichenkette in der Klasse ablegen - also kopieren. Da wir im C++-Teil dieses Forums sind: Was spricht gegen die Benutzung der Klasse String?



  • Sepp Brannigan schrieb:

    cout << vec;   /* wird intern zu ==> */   cout.operator<<( cout, vec );
    // bzw.
    cout << vec << endl;   /* zu ==> */   endl.operator<<( cout.operator<<( cout, vec ) );
    

    😕



  • PeterTheMaster schrieb:

    😕

    Antwort: 42


Anmelden zum Antworten