Objekt und Klasse und Konstruktoren
-
Hallo
Ich versuche mir ein Grundlagen Lehrbuch zu C++ zu erarbeiten. Dort heisst es (Zitat):
"In C++ you have the facility to encapsulate data and the operations that manipulate that data, in an appropriate object. This enables the use of these collections of data and function, called objects."
Später heisst es dann in dem Buch:
"The data items and the functions that manipulate them are combined into a structure called a class."
Ist jetzt ein Objekt und eine Klasse das gleiche oder was ist da der genaue Unterschied?
Dann noch eine Frage aus einem anderen Kapitel. Dort heisst es:
"More than one constructor, but only one destructor, can be declared for a class"
Also ein Konstruktor erzeugt und initialisiert ein Objekt und derer kann es mehrerer pro Objekt geben, aber ein Objekt kann nur einen einzige Destruktor besitzen. Was hat es denn damit auf sich? Wozu will man mehrere Konstruktoren für ein Objekt besitzen und wieso dann nur einen Destruktor?
Vermutlich für die Cracks ein paar dumme Fragen aber ich bin noch sehr neu auf dem Gebiet und kam bis dato sehr gut ohne Technik aus. Daher entschuldigt falls die Frage zu "dumm" ist.
Merci und Gruß
cpp_Jungspund
-
cpp_Jungspund schrieb:
Ist jetzt ein Objekt und eine Klasse das gleiche oder was ist da der genaue Unterschied?
Nein, eine Klasse ist wie ein Bauplan für ein Objekt. Ein Objekt ist eine Instanz der Klasse.
class SomeClass { //Das ist eine Klasse }; int main(){ SomeClass varname; SomeClass* varname2 = new SomeClass(); //Das sind beides Objekte, Instanzen der Klasse "SomeClass" }cpp_Jungspund schrieb:
Wozu will man mehrere Konstruktoren für ein Objekt besitzen und wieso dann nur einen Destruktor?
Nunja, ein Objekt kann auf die eine oder auf die andere Weise instanziert/konstruiert werden, z.B.:
class SomeClass { public: SomeClass(const char* name) : name(name) {}; SomeClass(const std::string& name) : name(name) {}; private: std::string name; }So kannst du ein Objekt mit einem (C++)-String oder einem C-String konstruieren, allerdings ist zur laufzeit bzw. nachdem das objekt konstruiert wird nichtmehr bekannt, welchen Konstruktor du genutzt hattest, um das Objekt zu erstellen, d.h. es gäbe keine Möglichkeit, gäbe es denn mehrere destruktoren, herauszufinden welcher der richtige wäre. Also bleibt nur der eine Destruktor, in dem du dich darum kümmern musst, alle resourcen freizugeben, egal durch welchen Konstrukor das Objekt konstruiert wurde.
-
Eine Klasse ist der Bauplan für Objekte. Beim Bau eines einzelnen Objekts kann einer der Konstruktoren verwendet werden. Beim Abreißen braucht man nur die Abrissbirne (aka Destruktor).
Wie alle Vergleiche hinkt auch dieser auf mindestens einem Bein.
-
Objekt verhält sich zu Klasse wie Plätzchen zu Plätzchenform.
Wozu will man mehrere Konstruktoren für ein Objekt besitzen
Warum nicht? willst du deine Plätzchen nur mit einem Teig backen können?
und wieso dann nur einen Destruktor?
Ok, hier bricht die Plätzchenanalogie etwas zusammen

Der Destruktor eines Objekts zerstört dieses unabhängig von allen anderen Dingen. Was sollte man so einem Destruktor auch sagen? Das einzige, was er wissen muss, ist, welches Objekt er zerstören soll. Und das heißt, dass es genau eine Destruktorvariante gibt, nämlich die, die als (verstecktes) Argument das zu zerstörende Objekt erhält und sonst nichts.
-
SeppJ schrieb:
Ok, hier bricht die Plätzchenanalogie etwas zusammen

Quatsch. Du kannst mit deinem eigenen (einzigen) Mund alle Plätzchen essen (zerstören), ganz egal aus welchem Teig sie gebacken sind

-
Aber viele verschiedene Münder können Plätzchen essen

-
Eine Klasse ist eine Beschreibung für eine Instanz (Objekt). Nach dieser Beschreibung wird dann eine Instanz gebaut. So ein Beschreibung besteht aus Datenelementen (du beschreibst, was den Zustand einer Instanz repräsentieren soll) und Elementfunktionen (du beschreibst, was eine Instanz können soll).
Eine Instanz ist etwas Lebendiges, sagen wir ein Akteur, mit dem du Dinge machen kannst. Welche Dinge dein Akteur machen kann, sagen die Elementfunktionen. Das Ergebnis einer Aktion sagen dann die Datenelemente. Die Datenelemente repräsentieren den aktuellen Zustand deiner Instanz.
Beispiel: Du hast eine Klasse Auto. Du erstellst ein Auto names KITT. Dann sagst du KITT.anhalten(). Das Ergebnis ist dann z.B. Datenelement kmh=0.
Ja ein Konstruktor initialisiert (baut) eine Instanz. Du kannst beliebig viele unterschiedliche Konstruktoren haben. Du kannst mehrere Konstruktoren haben, weil du willst, dann Instanzen auf unterschiedliche Art gebaut werden. Du willst ein Auto mit 50 PS bauen und du willst ein Auto mit 260 PS bauen. Wieso sollte es mehrere Destruktoren geben?
Hoffe, die Veranschaulichungen helfen dir weiter.
-
Die Antworten haben mir sehr geholfen. Danke sehr
-
Das es nur einen Destructor gibt, ist allein dem "maximale Effizienz" Ansatz von C++ geschuldet. Es waere kein Problem dem Konstruktor der Klasse einfach schon z.b. einen Funktionspointer mitzugeben, mit welchem man unter mehreren Destruktoren wechseln kann. Allein dieser muss pro Instanz gespeichert werden, und daher passiert dies eben nicht. Troztdem hat C++ schon eine Mechanik eingebaut, man kann den Destruktor virtual machen und dann in einer abgeleiteten Klasse überschreiben. Beim Konstruieren kann man sich dann den Destruktor waehlen. Das Objekt legt in der vtable die Daten ab um spaeter den passenden Destruktor zu finden, gab es vorher keine virtuelle Methode bezahlt man hier also diesen Preis.
-
TGGC schrieb:
Das es nur einen Destructor gibt, ist allein dem "maximale Effizienz" Ansatz von C++ geschuldet.
Ich würde nicht sagen "allein".
Selbst wenn man die runtime Kosten (Zeit + Speicher) ignoriert stellt sich immer noch die Frage "wozu?".
Und da fällt mir einfach kein guter Grund ein.
Also ich wüsste kein Beispiel wo ich, je nachdem wie das Objekt konstruiert wurde, einen anderen Destruktor verwenden wollen würde.
-
TGGC schrieb:
Das es nur einen Destructor gibt, ist allein dem "maximale Effizienz" Ansatz von C++ geschuldet.
Unfug.
-
hustbaer schrieb:
TGGC schrieb:
Das es nur einen Destructor gibt, ist allein dem "maximale Effizienz" Ansatz von C++ geschuldet.
Ich würde nicht sagen "allein".
Selbst wenn man die runtime Kosten (Zeit + Speicher) ignoriert stellt sich immer noch die Frage "wozu?".
Und da fällt mir einfach kein guter Grund ein.
Also ich wüsste kein Beispiel wo ich, je nachdem wie das Objekt konstruiert wurde, einen anderen Destruktor verwenden wollen würde.Du hast noch nie in einem Destructor ein if oder switch Statement verwendet? Immer wenn in einem Destructor Code ausgefuehrt wird, der dynamisch vom Zustand des Programms abhaengt, waeren mehrere Destruktoren doch lediglich syntaktischer Zucker um das Gleiche zu erreichen. Spontan fallen mir da unions ein.
Mit der Frage "wozu" kann man doch jede Funktion aus einer Programmiersprache entfernen, welche ueber eine Turingmaschine hinausgeht...
-
TGGC schrieb:
Du hast noch nie in einem Destructor ein if oder switch Statement verwendet?
Doch, klar. Aber kaum mit Bedingungen die nur immutable State prüfen.
TGGC schrieb:
Immer wenn in einem Destructor Code ausgefuehrt wird, der dynamisch vom Zustand des Programms abhaengt, waeren mehrere Destruktoren doch lediglich syntaktischer Zucker um das Gleiche zu erreichen.
Nur wenn der gesamte Destruktor als
T::~T() { if (condition) { // ... } else { // ... } }geschrieben werden kann.
Die Fälle wo das sinnvoll ist beschränken sich also auf Code wo die oben gezeigte Form ohne Codeduplizierung möglich wäre.Weiters eben die Sache mit dem mutable State. Bei so ziemlich allen Beispielen die mir einfallen müsste es die Möglichkeit geben den "designated destructor" nachträglich zu ändern. Das würde die Spezifikation verkomplizieren. Man müsste definieren wie man den dtor nachträglich ändern kann. Man müsste definieren was der compilerdefinierte operator = macht. Usw.
Und am Ende wäre der Nutzen immer noch so klein, dass es sich mMn. einfach nicht auszahlt den Sprachstandard und den Lernaufwand dadurch deutlich zu vergrössern.
Wenn man halbwegs durchgängig und feingranular RAII einsetzt ist die Anzahl der Klassen wo man überhaupt explizit definierte Destruktoren hat schonmal klein. Und nur in einem Bruchteil davon werden control-flow Statements vorkommen die man durch das "mehrere Destruktoren" Feature ersetzen könnte.TGGC schrieb:
Mit der Frage "wozu" kann man doch jede Funktion aus einer Programmiersprache entfernen, welche ueber eine Turingmaschine hinausgeht...
Nicht wenn man damit meint dass man den Aufwand dem Nutzen gegenüberstellen sollte.
(Wobei zum Aufwand natürlich nicht nur der Aufwand zählt der nötig ist um das Feature zu spezifizieren und in den Compilern zu implementieren, sondern auch wie oben schon erwähnt der Lernaufwand für neue Programmierer.)
Ich dachte eigentlich dass klar war dass ich es so gemeint habe.
-
Mit den gleichen Argumenten könntest du z.b. auch mehrere Konstruktoren ablehnen. Der Unterschied ist lediglich, das es dieses Feature schon gibt und du deshalb gewöhnt bist Anwendungen dafür zu kennen.
-
Nein, könnte ich nicht.
Liest du überhaupt was ich schreibe?
Oder willst du mich einfach nur aufziehen?
Alter Schwede...
-
schau mal hier: http://www.cpp-tutor.de/cpp/le10/ctor_dtor.html
-
hustbaer schrieb:
Nein, könnte ich nicht.
Wer sollte dich hindern?
-
TGGC schrieb:
hustbaer schrieb:
Nein, könnte ich nicht.
Wer sollte dich hindern?
Logik? Das Argument bricht doch schon beim allerersten Schritt zusammen, wenn es um Parameter für die Konstruktion geht.
-
Kosten:
Mehrere Konstruktoren zu erlauben macht in einer Sprache die bereits Overloads erlaubt nichts wesentlich komplizierter. Die Overload-Resolution Regeln gibt es bereits, der Ctor wird ganz normal anhand dieser ausgewählt.
Davon abgesehen wird nichts verkompliziert. Es müssen keine speziellen Regeln definiert werden was beim operator = zu passieren hat, es muss kein zusätzlicher State in das Objekt rein.Nutzen:
Mehrere Konstruktoren sind nötig um flexible konsturierbarkeit von Klassen zu ermöglichen wenn diese...
* const Member haben
* Member haben die nur per Ctor initialisiert werden können (d.h. nicht default konstruiert und danach so verändert werden können dass sie "passen").
Weiters erspart man sich dadurch lauter "named Constructor" Funktionen zu basteln.Weiters sind mehrere Konstruktoren nötig für kopierbare und konvertierbare Klassen.
---
Der Nutzen ist also ziemlich klar und mMn. auch ziemlich gross, und die Kosten sind minimal.
Also genau umgekehrt wie beim Destruktor.
-
Erhard Henkes schrieb:
schau mal hier: http://www.cpp-tutor.de/cpp/le10/ctor_dtor.html
An wen ist das gerichtet und was soll er/sie da "schauen"? Einen ca. 10 seitigen Artikel mit nur "schau mal da" zu verlinken, in dem auf den ersten Blick nichts zu sehen ist was wirklich zum Thema passt, finde ich ein bisschen unpassend.