protected Vererbung
-
blurry333 schrieb:
oki

Was ich immer noch nicht versteh welchen Sinn macht es,
einen Basisklassen Zeiger auf eine abgeleitete Klasse zeigen zu lassen.
Nur dann kommt ja auch der virtual Destruktor ins Spiel.
Warum nicht einen abgeleiteten Zeiger auch auf eine abgeleitete Klasse zeigen lassen. Kostet das mehr oder wo liegt das Problem. Es kostet insofern mehr
dass ich ja dann auch die Methoden von B selber zur Verfügung habe.
Will man das wohl nicht ?Da kommt das mit dem virtual in's Spiel. Das kann man ja nicht nur mit dem Destruktor machen sondern auch mit allen anderen Methoden. Und das ist sehr oft erwünscht. Zum Nachschlagen: Das nennt sich Polymorphie.
-
blurry333 schrieb:
oki

Was ich immer noch nicht versteh welchen Sinn macht es,
einen Basisklassen Zeiger auf eine abgeleitete Klasse zeigen zu lassen.
Nur dann kommt ja auch der virtual Destruktor ins Spiel.Ich hab gerade Bananen im Supermarkt gekauft, jetzt lege ich sie in einen
(selbstentsorgenden) Obstkorb. Wenn die Früchte darin verfault sind, werden
sie weggeworfen (gelöscht). Jetzt interessiert den Obstkorb nicht, ob ne Banane oder
nen Apfel verfault ist, sondern er wirft das Obst einfach weg (delete obst)EDIT: Obst hat natürlich ne Funktion getVerfallsdatum()
Vielleicht etwas albern, aber evtl hilft es

-
class Obst{public: void verfaulen(){}}; class Banane:public Obst { public: void reifen(){} }; int main() { Obst* x= new Banane ; // macht das hier Sinn ??? //oder Banane* x=new Banane; // jetzt kann man wenigstens auf reifen() zugreifen }
-
class Point2D { public: virtual ~Point2D(){} private: double m_x, m_y; };sizeof(Point2D) ergibt 24 Byte
wenn ich aber im private statt double 2 int deklariere bekomme ich 12 Byte.
Wie gibts das ?
-
double ist kleiner als int, deswegen.
-
Stell dir mal vor, du hast sowas hier:
Obst *liste[3];Dann kannst du das hier machen:
liste[0] = new Apfel(); liste[1] = new Birne(); liste[2] = new Banane();
-
ghostboss schrieb:
double ist kleiner als int, deswegen.
Geh ins Bett o.O
Double hat die Große 8
Int hat die Größe 4
Pointer ist ebenfalls 4.2x Double + virtual Pointer ergibt 20 angezeigt 24, da werden 4 Bytes als Padding verwendet.
http://msdn.microsoft.com/en-us/library/ms253935.aspx2x Int + virtual Pointer ergibt 12 angezeigt 12
-
Diese Klasse hat die unglaubliche Größe von 32 Byte.
Wie gibts das. char sagen wir mal 4 Byte *2 + 2*double = 24 ByteWahrscheinlich um auf eine gerade Speicheradresse zu kommen.
Das Padding kann ja ganz schön speicher kosten

class B { public: B(void); ~B(void); private: char m_1; double m_3; char m_2; double m_4; };
-
Zeus schrieb:
Double hat die Große 8
Int hat die Größe 4
Pointer ist ebenfalls 4.Diese Größen sind (strenggenommen) Compiler- und System-abhängig.
Bei meinem 64-bit System ist ein Pointer z. B. 8 Byte.
-> Ich vermute du hast (noch) ein 32-bit System?
-
blurry333 schrieb:
Diese Klasse hat die unglaubliche Größe von 32 Byte.
Wie gibts das. char sagen wir mal 4 Byte *2 + 2*double = 24 ByteWahrscheinlich um auf eine gerade Speicheradresse zu kommen.
Das Padding kann ja ganz schön speicher kosten

class B { public: B(void); ~B(void); private: char m_1; double m_3; char m_2; double m_4; };Änder einfach mal die Reihenfolge in char, char, double, double oder
in double, double, char, char und du hast (wahrscheinlich) nur noch 24 Byte
-
Nö, 64 bit, heisst aber nicht, dass ich auch in 64-Bit Mode kompiliere *gg*
-
Zeus schrieb:
Nö, 64 bit, heisst aber nicht, dass ich auch in 64-Bit Mode kompiliere *gg*
Mir war klar, dass du nur die Größenangaben begründen wolltest.
Die 32-bit Aussage ging Richtung blurry333Hast du wirklich im 32bit Modus kompiliert? Ich hätte gesagt, du hast gar nichts kompiliert

-
CSpille schrieb:
Zeus schrieb:
Double hat die Große 8
Int hat die Größe 4
Pointer ist ebenfalls 4.Diese Größen sind (strenggenommen) Compiler- und System-abhängig.
Bei meinem 64-bit System ist ein Pointer z. B. 8 Byte.
-> Ich vermute du hast (noch) ein 32-bit System?Ups ich hab ja auch ein 64 Bit Windows 7 Betriebssystem.
-
aber :
int main() { int y=7; int *x=&y; cout<<sizeof(x); // Ausgabe 4 Byte !!! }
-
Dann hast du dein Programm wohl für 32 Bit kompiliert.
-
blurry333 schrieb:
WAnn macht es Sinn den Destruktor selbst zu definieren. ABgesehen von virtual destruktor ?
Einen eigenen Destruktor brauchst Du immer dann, wenn der Defaultdestruktor nicht alles abräumen kann. Der Defaultdestruktor ruft einfach die Destruktoren aller Membervariablen auf. Sonst macht der nichts. Wenn eine Deiner Membervariablen z.B. ein Pointer ist, mußt Du einen eigenen Destruktor erzeugen, der den Speicher eventuell frei gibt:
class x { TYPE *pointer; x() { pointer=NULL } ~x() { if( pointer ) free(pointer); } // oder delete pointer; .... };Der Default destruktor würde den Speicher nicht freigeben. Gleiches gilt auch für Filehandles, Fensterhandles und ähnliches.
mfg Martin
-
mgaeckler schrieb:
~x() { if( pointer ) free(pointer); } // oder delete pointer;mgaeckler meinte natürlich:
~x() { if( pointer ) delete pointer; } // oder (in Ausnahmen) free(pointer);Jetzt verführ keinen Neuling dazu malloc und free zu benutzen

@blurry333: In C++ verwendet man i. d. R. new und delete

-
blurry333 schrieb:
oki

Was ich immer noch nicht versteh welchen Sinn macht es,
einen Basisklassen Zeiger auf eine abgeleitete Klasse zeigen zu lassen.Ich habe beispielsweise eine Klassenbibliothek für die Windows API.
Die Basisklasse kapselt das Fensterhandle. Abgeleitete Klassen spezialisieren sich dann immer mehr:
Selbstdefinierte Windowsklassen,
Edit Controls, Comboboxen, Listboxen, MDI-Fenster, MDI-Childs usw. usf.Einer meiner Container enthält eine Liste aller Fenster mit selbst definierten Klassen. Der Container selber kennt aber nur die BASIS-Klasse aller selbst defnierten Fenster. Applikationsspezifische Klassen kann er gar nicht kennen, da er Teil der Bibliothek ist.
Er liefert daher immer nur einen Zeiger auf die Basisklasse zurück. Wenn der Anwendung in dem Kontext das auch genügt, wird sie das auch so lassen. Ansonsten muß halt gecastet werden.
Der Container ist auch dafür verantworlich, Windows Messages an die Instanzen der Fensterklassen zu verteilen. Dafür sind dann die virtuellen Funktionen zwingend erforderlich, da er applikationsspezifische Messagehandler gar nicht kennen kann.
Generel brauchst Du das, wenn ein Container Zeiger auf Instanzen von Klassen speichern muß, bei denen er nur die Basisklasse kennt.
mfg Martin
-
CSpille schrieb:
Jetzt verführ keinen Neuling dazu malloc und free zu benutzen

Was soll an
char *x=new char[100]; ... delete [] x;besser sein als an
char *x =(char *)malloc( 100 ); ... free( x );?
OK, ich muß den Zeiger nicht casten, aber das ist ja wohl ein akademischer Unterschied.
Hab ich was übersehen?
mfg Martin
-
mgaeckler schrieb:
CSpille schrieb:
Jetzt verführ keinen Neuling dazu malloc und free zu benutzen

Was soll an
char *x=new char[100]; ... delete [] x;besser sein als an
char *x =(char *)malloc( 100 ); ... free( x );?
OK, ich muß den Zeiger nicht casten, aber das ist ja wohl ein akademischer Unterschied.
Hab ich was übersehen?
mfg Martin
Weiss nicht ob Du's übersehen hast, aber...
Bei new und delete wird der Konstruktor und Destruktor aufgerufen. Bei malloc und free nicht. Spielt bei char keine Rolle... aber eben nicht geeignet, das dem Anfänger hinzuschmeissen.Simon