Virtual sinnhaft?
-
wiwie schrieb:
Bei einem Zugriff über einen Pointer auf eine nicht-virtuelle Methode wird ja auf jeden Fall die Methode der Basisklasse ausgeführt. Weshalb ist das so? Wieso wird nicht die implizit-vorhandene Methode der Subklasse verwendet? Geht es eventuell um Performance, dass die selbe Methode nicht zweimal vorhanden ist?
Genau, Performance ist sicher der wichtigste Grund, warum man als Programmierer entscheiden kann, ob eine Methode virtuell ist oder nicht. Es gibt angeblich auch Situationen, in denen eine nicht-virtuelle Methode aus Designgründen vorteilhaft ist, aber die entfleuchen mir immer wieder

-
wiwie schrieb:
Hallo otze,
ja so meinte ich das auch nicht. Mir war bewusst, dass Subklassen die Methoden der Basisklasse überschreiben können.Mir ist nur nicht klar, weshalb das Schlüsselwort virtual überhaupt benötigt wird. Es kann ja nicht darum gehen, dem Compiler mitzuteilen, dass die Methode in den Subklassen existiert, denn das tut sie ja auf jeden Fall.
Aber woher soll der Compiler wissen, dass es überhaupt Subklassen gibt?
Du verwendest virtual, um dem Compiler zu sagen, dass er abhängig vom Objekttyp entscheiden soll, welche Funktion gerufen wird. Ein Objekt, dessen Klasse (oder Basisklassen) über mindestens eine virtuelle Funktion verfügt, besitzt einen Zeiger auf eine sogenannte VTable.
Du kannst das verifizieren, indem Du sizeof auf eine Klasse mit virtueller Funktion (z.B. destructor) ausführst und auf eine Klasse mit identischen Daten, aber ohne virtuelle Funktion. Die Klasse mit virtueller Funktion ist 4 Byte größer.Die VTable enthält die Information, um welchen Objekttyp es sich handelt und ebenso für jede virtuelle Funktion einen Zeiger die Funktion, die zum jeweiligen Objekttyp gehört.
wiwie schrieb:
Bei einem Zugriff über einen Pointer auf eine nicht-virtuelle Methode wird ja auf jeden Fall die Methode der Basisklasse ausgeführt. Weshalb ist das so? Wieso wird nicht die implizit-vorhandene Methode der Subklasse verwendet? Geht es eventuell um Performance, dass die selbe Methode nicht zweimal vorhanden ist?
Im einen Fall wird objektorientiert über den Objekttyp entschieden, in dem über die VTable die richtige Funktion gewählt wird. Das kostet 2x dereferenzieren und eine Addition zusätzlich.
Ohne virtual wird nur ein statischer Sprung ausgeführt und der landet dann in der Funktion, die dem Referenztyp entspricht. Solltest Du OOP nicht brauchen, vermeide virtual.otze: Jedem das Recht auf freie Meinungsäußerung - Du Deine, ich meine... Hier entsteht kein neuer 40 Seiten-Thread.
-
Ich bitte dich nur darum, deine propaganda aus real world themen rauszuhalten. sowas wollte der threadstarter sicher net. danke.
-
Xin schrieb:
...
Du kannst das verifizieren, indem Du sizeof auf eine Klasse mit virtueller Funktion (z.B. destructor) ausführst und auf eine Klasse mit identischen Daten, aber ohne virtuelle Funktion. Die Klasse mit virtueller Funktion ist 4 Byte größer....Hohoho !!
DEN Absatz im Standard hätte ich jetzt aber gerne mal gesehen !

Gruß,
Simon2.
-
Xin schrieb:
otze: Jedem das Recht auf freie Meinungsäußerung
OT: wunderlich, dass Leute bei etwas wie einer Programmiersprache, die durch einen Standard von mehreren hundert Seiten festgelegt ist, von Meinugnen sprechen. Bei der Verwendung kann man Präferenzen haben - ok. aber hier geht es um einen simplen Sprachbestandteil. Wenn es darüber verschiedene Meinungen gäbe, würde jeder Compilierungsversuch in eine Diskussion mit dem Compiler ausarten

-
pumuckl schrieb:
Xin schrieb:
otze: Jedem das Recht auf freie Meinungsäußerung
OT: wunderlich, dass Leute bei etwas wie einer Programmiersprache, die durch einen Standard von mehreren hundert Seiten festgelegt ist, von Meinugnen sprechen. Bei der Verwendung kann man Präferenzen haben - ok. aber hier geht es um einen simplen Sprachbestandteil. Wenn es darüber verschiedene Meinungen gäbe, würde jeder Compilierungsversuch in eine Diskussion mit dem Compiler ausarten

Schaut man sich an, wie C++ virtual übersetzt, sollte auffallen, dass ich hier keine Meinung beschreibe - auch wenn die Form der Übersetzung weder durch den Standard vorgegeben ist noch die einzig machbare Möglichkeit darstellt.
-
es ist toll wie xin alles so hindrehen kann, dass es ihm passt und er die tollen fakten liefert. xins meinung ist, dass man nur oop macht, wenn man auch virtual verwendet. xins meinung ist es, dass ein virtual methodenaufruf viel zuviel zeit braucht, weil man ein paar operationen mehr hat. und das sind natürlich fakten, weil er uns vorrechnen kann, das ein virtual methodenaufruf x-mal langsamer ist. das programme natürlich nicht ihre hauptzeit beim methodenaufruf verbringen, sondern ganz wo anders ignoriert er.
virtual hat eigentlich so gut wie nur was mit performance zu tun, wobei ich stark bezweifle, dass man bei normalen programmen damit mehr als 1% ruasholen kann. ich weiß auch nicht, ob irgendeine sprache auser c++ diese entscheidungsmöglichkiet anbietet. java hat immer virtual methoden.
-
virtuelle Methoden sind dann sinnvoll, wenn man eine Schnittstelle zu ganz vielen verschiedenen klassen haben möchte. So kann man auch Objekte unterschiedlicher Klassen in einer Datenstruktur speichern.
Beispiel:
in einer Grafikengine soll jedes Objekt gezeichnet werden, dazu sind alle sichtbaren Objekte in einer Liste (List<*ADT_visual_object>). wenn jetzt verschiedenste Klassen alle von ADT_visual_object abgeleitet sind, können sie ihre methode "void draw();" auf unterschiedlichste weise implementieren. wenn die Liste durchiteriert wird und für jedes objekt draw() aufgerufen wird, dann wird immer das entsprechende draw aus der abgeleiteten Klasse aufgerufen. Das ist nur möglich, wenn ADT_visual_object auch die Methode draw als visual Prototyp besitzt.
Ich hoffe ich hab mich jetzt nicht zu verkorkst ausgedrückt
-
kindergarten schrieb:
es ist toll wie xin alles so hindrehen kann, dass es ihm passt und er die tollen fakten liefert. xins meinung ist, dass man nur oop macht, wenn man auch virtual verwendet. xins meinung ist es, dass ein virtual methodenaufruf viel zuviel zeit braucht, weil man ein paar operationen mehr hat. und das sind natürlich fakten, weil er uns vorrechnen kann, das ein virtual methodenaufruf x-mal langsamer ist. das programme natürlich nicht ihre hauptzeit beim methodenaufruf verbringen, sondern ganz wo anders ignoriert er.
virtual hat eigentlich so gut wie nur was mit performance zu tun, wobei ich stark bezweifle, dass man bei normalen programmen damit mehr als 1% ruasholen kann. ich weiß auch nicht, ob irgendeine sprache auser c++ diese entscheidungsmöglichkiet anbietet. java hat immer virtual methoden.
Was soll den der Kindergarten? Xin hat mehrmals geschrieben das virtual eine Technik ist, die eben nicht kostenlos ist (so wie alle Techniken). Wenn man sie braucht, dann braucht man sie eben. Wenn man sie aber nicht braucht, dann sollte man auf sie verzichten, weil sie eben Kosten verursacht. Das sie Kosten verursacht, das steht ja wohl ausser Frage...
-
es gibt halt viele menschen die gerne an der falschen stelle optimieren.
-
Nicht-Virtuelle Methoden zu verwenden macht IMHO dann Sinn, wenn der Speicher sehr begrenzt ist, da jede virtuelle Methode einen Zeiger in der Funktionstabelle benötigt. Das mag bei PCs mit Speicher im GB Bereich egal sein, bei einem Microcontroller mit 1 oder 2KB RAM, sollte man schon dreimal überlegen, ob man hier
die virtuelle Methode wirklich benötigt. Und da Portabilität nun mal einer der Hauptaspekte bei der Entwicklung von C/C++ war, ermöglicht die Sprache eben, selbst zu entscheiden, welche Methoden virtuell sein sollten...Grüße,
Martin
-
JimmydaMage schrieb:
bei einem Microcontroller mit 1 oder 2KB RAM, sollte man schon dreimal überlegen, ob man hier
die virtuelle Methode wirklich benötigt.Nein, da braucht man das gar nicht zu überlegen; für so einen Controller hat man bestenfalls einen C-Compiler

-
JimmydaMage schrieb:
Nicht-Virtuelle Methoden zu verwenden macht IMHO dann Sinn, wenn der Speicher sehr begrenzt ist, da jede virtuelle Methode einen Zeiger in der Funktionstabelle benötigt. Das mag bei PCs mit Speicher im GB Bereich egal sein, bei einem Microcontroller mit 1 oder 2KB RAM, sollte man schon dreimal überlegen, ob man hier
die virtuelle Methode wirklich benötigt. Und da Portabilität nun mal einer der Hauptaspekte bei der Entwicklung von C/C++ war, ermöglicht die Sprache eben, selbst zu entscheiden, welche Methoden virtuell sein sollten...Der Speicher ist nahezu uninteressant, selbst bei begrenzten Systemen. Die VTable ist 4 Byte + (4 Byte * Anzahl virtueller Funktionen) groß, also auch bei sehr flexiblen Objekten überschaubar.
Wichtig ist, dass sich (unnötige) virtuelle Funktionen nicht in (geschachtelten) Schleifen finden. Hier kann alleine ein einfacher Zugriff (Stack->Object->Element) einen Algorithmus stark beschleunigen, wenn man vor der Schleife "temp = Object->Element" setzt und so eine Addition und Dereferenzierung spart: Stack->temp.
Bei einer virtuellen Funktion lautet der Zugriff Stack->Objekt->VTable->Funktion( Stack->Objekt ) statt static_func( Stack->Object );Die Berücksichtigung dieser Sachlage machte bei einer Optimierung, die ich vor ein paar Monaten machte, bedeutete einen Laufzeitunterschied von ursprünglich 60s auf 25s. Dereferenzierungen sind nicht teuer, können sich aber in Algorithmen, die große Datenmengen verarbeiten, teuer aufaddieren.
Computer sind heutzutage schneller als früher, aber das hilft nur bedingt, viele Programmierer argumentieren damit, dass man deswegen nicht mehr so aufmerksam programmieren muss.
Ein Prof von mir formulierte das provokanter: "Programmierer werden noch schneller dumm, als Computer schneller."
-
Xin schrieb:
Ein Prof von mir formulierte das provokanter: "Programmierer werden noch schneller dumm, als Computer schneller."
dumm nicht, eher faul und bequem. ob das jetzt gut oder schlecht ist, ist eine andere frage.

-
Xin schrieb:
wiwie schrieb:
Hallo otze,
ja so meinte ich das auch nicht. Mir war bewusst, dass Subklassen die Methoden der Basisklasse überschreiben können.Mir ist nur nicht klar, weshalb das Schlüsselwort virtual überhaupt benötigt wird. Es kann ja nicht darum gehen, dem Compiler mitzuteilen, dass die Methode in den Subklassen existiert, denn das tut sie ja auf jeden Fall.
Aber woher soll der Compiler wissen, dass es überhaupt Subklassen gibt?
Warum sollte er es nicht wissen? Es gibt doch in C++ garnicht die Möglichkeit Klassen zur Laufzeit zu laden. Also weiß doch der Compiler ob es Subklassen gibt und ob diese eine Methode überschreiben. Wieso kann der Compiler dann das setzen von virtual nicht automatisch machen?
-
In vielen Fällen weiß es nicht der Compiler, sondern frühestens der Linker. Und solange der ein C-Linker bleibt, hat er keinen Eingriff in den Compiliervorgang.
Und außerdem gibts DLLs, mit denen sowas wie "Klassen zur Laufzeit laden" praktikabel ist

-
Auf jeden Fall kann er nicht wissen, auf welches Objekt ein Pointer zur Laufzeit zeigt.
Und je nachdem, ob der Pointer auf ein Objekt die Basisklasse oder der abgeleiteten Klasse ist, muss die entsprechende Funktion ausgewählt werden - das ist ja der Sinn von virtual ;)./Edit:
Was ist eigentlich hier genau mit "Klassen zu Laufzeit laden" gemeint?
-
Was ist eigentlich hier genau mit "Klassen zu Laufzeit laden" gemeint?
Eine Instanz per 'new' auf dem Heap anlegen.
-
mikey schrieb:
Was ist eigentlich hier genau mit "Klassen zu Laufzeit laden" gemeint?
Eine Instanz per 'new' auf dem Heap anlegen.
öhm dann würde mich mal interessieren, wieso das in C++ ncht geht soll^^ - hab ich was verpasst?
Wobei eine Instanz aufm Heap ablegen, würde ich eher als Objekt zur Laufzeit laden bezeichnen ... Klassen zur Laufzeit laden hieße meinem Gefühl nach, dass man die Klassendefinition zur Laufzeit kennt -> wie ein Vorredner schon angesprochen hat, über DLLs machbar.
-
audacia schrieb:
In vielen Fällen weiß es nicht der Compiler, sondern frühestens der Linker. Und solange der ein C-Linker bleibt, hat er keinen Eingriff in den Compiliervorgang.
Also ne moderne IDE kann doch anzeigen, ob es mehrere gleiche methoden gibt, wenn ich von nem Aufruf zur Definition springen will. So schwer kann das nicht sein.
Und außerdem gibts DLLs, mit denen sowas wie "Klassen zur Laufzeit laden" praktikabel ist

Da muss aber vorher die Deklaration bekannt sein, oder?
mikey schrieb:
Was ist eigentlich hier genau mit "Klassen zu Laufzeit laden" gemeint?
Eine Instanz per 'new' auf dem Heap anlegen.
Nein.
Sowas wie in Java Class.forName und Methodennamen per Reflection ermitteln und das ganz Zeug.