Diese klasse so in ordnung?Tipps und Hinweise!
-
//--------------------------------------------------------------------------- #pragma hdrstop #include <iostream> #include <conio> #include <string> #include <strstream> using namespace std; //--------------------------------------------------------------------------- #pragma argsused class IntFeld { public: IntFeld(int size = 0, int initDigit = 0); IntFeld(const IntFeld& Feld); ~IntFeld(); IntFeld& operator=(const IntFeld& Feld); int top()const; int first()const; int at(int index); void pushBack(int digit); void pop(); int getSize()const; int operator[](int index); friend ostream& operator<<(ostream& ostr,const IntFeld& Feld); friend istream& operator>>(istream& istr,const IntFeld& Feld); string GetLastError(); bool isEqual(const IntFeld& Feld); bool operator==(const IntFeld& Feld); private: int m_index; int* m_data; int m_size; string m_errormsg; }; //-------------------------------------------------------------------------- IntFeld::IntFeld(int size, int initDigit) { m_data = new int[size]; for(int i = 0; i < size; ++i) m_data[i] = initDigit; m_size = size; m_index = -1; } //-------------------------------------------------------------------------- IntFeld::IntFeld(const IntFeld& Feld) { m_data = new int[Feld.m_size]; m_size = Feld.m_size; m_index = Feld.m_index; for(int i = 0; i < m_size; ++i) m_data[i] = Feld.m_data[i]; } IntFeld::~IntFeld() { delete[] m_data; m_data = 0; m_index = -1; m_size = 0; } //-------------------------------------------------------------------------- IntFeld& IntFeld::operator=(const IntFeld& Feld) { if(this!=&Feld) { delete[] m_data; m_size = 0; m_index = -1; m_size = Feld.m_size; m_data = new int[m_size]; for(int i = 0; i < m_size; ++i) { m_data[i] = Feld.m_data[i]; } m_index = Feld.m_index; } return *this; } //-------------------------------------------------------------------------- int IntFeld::top()const { return m_data[m_index]; } //-------------------------------------------------------------------------- int IntFeld::first()const { if(m_data) { if(m_index>-1) return m_data[0]; } return 0; } //-------------------------------------------------------------------------- int IntFeld::at(int index) { if(index>m_index || index< -1) { string indexer; strstream str; str<<index; str>>indexer; str.str(); m_errormsg = "Index "; m_errormsg += indexer; m_errormsg += " out of range"; throw std::out_of_range(m_errormsg.c_str()); } else return m_data[index]; } //-------------------------------------------------------------------------- void IntFeld::pushBack(int digit) { m_index = m_index+1; //wenn größe des Arrays noch reicht if(m_index <= m_size) { m_data[m_index] = digit; } else //wenn array zu klein { //Altes Array in tempo kopieren; int* temp = new int[m_index]; for(int i = 0; i < m_index+1; ++i) temp[i] = m_data[i]; delete[] m_data; m_size = m_index + 10; //neues array allokoieren und füllen m_data = new int[m_size]; for(int i = 0; i < m_index+1; ++i) m_data[i] = temp[i]; m_data[m_index] = digit; delete[] temp; } } //-------------------------------------------------------------------------- void IntFeld::pop() { if(m_data && m_index>-1) { m_data[m_index] = 0; m_index-=1; } else { m_errormsg = "Kontainer nicht initialisiert oder index out of range"; throw m_errormsg.c_str(); } } //-------------------------------------------------------------------------- int IntFeld::getSize()const { return m_size; } //-------------------------------------------------------------------------- int IntFeld::operator[](int index) { if(index > m_index) return 0; else return m_data[index]; } //-------------------------------------------------------------------------- ostream& operator<<(ostream& ostr,const IntFeld& Feld) { for(int i = 0; i < Feld.m_index+1; ++i) ostr<<"Element "<<i<<": "<<Feld.m_data[i]<<endl; return ostr; } //-------------------------------------------------------------------------- string IntFeld::GetLastError() { return m_errormsg; } //-------------------------------------------------------------------------- bool IntFeld::isEqual(const IntFeld& Feld) { if(m_size==Feld.m_size) { for(int i = 0; i < m_size; ++i) { if(m_data[i]!=Feld.m_data[i]) return false; } return true; } else return false; } //-------------------------------------------------------------------------- bool IntFeld::operator==(const IntFeld& Feld) { return isEqual(Feld); } //-------------------------------------------------------------------------- } //---------------------------------------------------------------------------was sagt ihr zu dieser klasse?
was habe ich falsch gemacht?
was könnte ich besser machen?gibt es speicherlecks?
Das ist eine übung und bringt keine fehler, möchte nur eure meinung und tipps hören!
-
Du solltest versuchen, diesen pragma-"müll" nicht zu verwenden, solange du es nicht wirklich nötig hast
dann hast du noch nicht überall wo möglich const verwendet. Ich meine damit zum Beispiel bei operator== und so.
-
Auf Anhieb sieht die Klasse schon recht gut aus, allerdings:
- Die Speicherverwaltung wird auf Dauer etwas zeitaufwändig, wenn du nacheinander viele Elemente einfügst
(std::vector<> verdoppelt die Kapazität, wenn er voll ist) - du hast keine Methoden, um bestehende Elemente der Liste ändern zu können
(at() und op[] brauchst du in zwei Versionen -int at(int index) const;(lesender Zugriff bei konstantem Feld) undint& at(int index);(freier Zugriff bei nicht-konstantem Feld)) - du wirfst Zeiger auf Zeichenketten, die im Rahmen des Stack Unwinding vor dem catch() entsorgt wurden, also bekommt der Aufrufer im Fehlerfall nur Müll
(wirf lieber ein std::runtime_error-Objekt (oder eine davon abgeleitete Klasse))
PS: Was für einen Grund hat es, das selber zu schreiben. Was du dort hast, kannst du alles mit std::vector<int> erledigen (eventuell außer op<< und op>>).
- Die Speicherverwaltung wird auf Dauer etwas zeitaufwändig, wenn du nacheinander viele Elemente einfügst
-
Hmmm, ist alles nicht ganz Exception-Sicher. Versuche in den Funktion in denen die Daten verändert werden erstmals diese Veränderung zB temporär zu machen und nachher diese dann erst übernehmen. ZB bei op= erstmal ein temporäres IntFeld Objekt erzeugen und nachher swappen ...
Vielleicht mache ich das heute Abend mal

Am besten in Exceptional C++ die Kaptitel über Exceptions lesen ( einfach traumhaft ) ...