Mixer S. schrieb:> was bringt dann die virtuelle Funktion in der Basisklasse?> Glaub ich steh grad auf m Schlauch...
Bei einer Datenstruktur wie beispielsweise einer Liste, deren
verschiedenartige Elemente alle von "Basis" abgeleitet sind, kannst du
über diese Liste nur auf Funktionen zugreifen, die in "Basis" deklariert
wurden.
Mixer S. schrieb:> Hallo,>> was bringt dann die virtuelle Funktion in der Basisklasse?
Auch die Basisklasse kann ja seine eigenen Vorstellungen davon haben,
wie die Funktion get() zu implementieren ist.
1
classNeu:publicBasis{
2
inta;
3
};
> Wenn ich jetzt z.B. die Funktion get für die abgeleitete Klasse> implementieren will nicht. Laut g++ gibts keine Funktion get in Neu.
Recht hat er. In der Klasse Neu gibts tatsächlich keine eigene Funktion
get(). Die Klasse Neu würde die Funktion aus Basis erben, wenn du nichts
unternimmst. Wenn du aber willst, dass Neu seine eigene Version von
get() hat, dann musst du das auch bekannt geben (in Form der Deklaration
in der Klasse).
Alles was nicht explizit in einer abgeleiteten Klasse in der Deklaration
drinnen steht, wird stillschweigend von der Basisklasse geerbt und
bleibt so, wie es die Basisklasse vorgegeben hat.
Karl heinz Buchegger schrieb:> Recht hat er. In der Klasse Neu gibts tatsächlich keine eigene Funktion> get(). Die Klasse Neu würde die Funktion aus Basis erben, wenn du nichts> unternimmst. Wenn du aber willst, dass Neu seine eigene Version von> get() hat, dann musst du das auch bekannt geben (in Form der Deklaration> in der Klasse).
Dann gibts z.B. rein virtuelle Methoden nur, damit man eine abgeleitete
Klasse dazu zwingt diese zu implementieren?
MFG Mixer
Hey,
aber man muss doch nicht die Methode in der abgeleiteten Klasse (class
Neu : public Basis) auch als virtual deklarieren, oder irre ich mich da?
Nur wenn diese Methode von einer weiteren Klasse (z.B. class GanzNeu :
public Neu) eigens implementiert werden soll/kann.
Gru0
inok
Markus K. schrieb:> aber man muss doch nicht die Methode in der abgeleiteten Klasse (class> Neu : public Basis) auch als virtual deklarieren
Musst du nicht; eine Methode ist virtuell in allen abgeleiteten
Klassen, sobald sie es in einer Basis ist.
Aber es erhöht die Lesbarkeit der abgeleiteten Klasse deutlich, wenn
man es dort auch hinschreibt.
Markus K. schrieb:> Nur wenn diese Methode von einer weiteren Klasse (z.B. class GanzNeu :> public Neu) eigens implementiert werden soll/kann.
Das kann man mit oder ohne virtual, egal wo.
Der Unterschied ist wie schon seinerzeit Sebastian Hepp sagte:
Man braucht es für Polymorphismus.
Solange man ohne auskommt, kann man virtual weglassen.
(Nicht sehr OO-like, kann aber auf Controllern viel Platz und
Laufzeit sparen.)
Mixer S. schrieb:> Dann gibts z.B. rein virtuelle Methoden nur, damit man eine abgeleitete> Klasse dazu zwingt diese zu implementieren?
Gehts nur mir so?
Klaus, wie machst du das in deinen Kursen?
Nennst du 'pure' Functions im Deutschen 'reine' Funktionen? Wenn man es
weiß ist es ok, umgangssprachlich hat aber 'rein virtuell' eine
Doppelbedeutung. So wie 'rein weiß' (also nicht grau) im Gegensatz zu
'reinem Rot'.
Ich finde die Bezeichnung nicht so glücklich.
Übrigens: Ein weit verbreiteter Irrtum besteht darin anzunehmen, dass
pure Functions keine Implementierung haben können.
1
classBasis{
2
public:
3
virtualintget()=0;
4
virtualvoidput(int)=0;
5
};
6
7
intBasis::get()
8
{
9
std::cout<<"should not be called, but it is ok for now\n";
10
return0;
11
}
12
13
intBasis:put(inti)
14
{
15
std::cout<<"should not be called, but it is ok for now\n";
16
std::cout<<"will do default working\n";
17
return0;
18
}
Von einer Klasse, die pure Functions enthält und die nicht mit nicht
puren Functions überschrieben wurden, kann kein Objekt erzeugt werden.
Das ist alles was pure Functions bewirken. Das impliziert natürlich,
dass alle pure Functions einer Basisklasse mit nicht-puren Varianten
spätestens am Ende der Klassenhierarchie überschrieben werden müssen.
Mittels pure Functions baut man sich in C++ zb das auf, was in Java ein
"Interface" ist. Also eine Basisklasse, die nur einen einzigen Zweck
hat: Zu definieren, welche Funktionen eine andere Klasse implementieren
muss, um als von einem bestimmten Typ zu gelten.
Und noch etwas. Wenn deine Klasse mindestens 1 virtuelle Funktion hat
(egal ob pure oder nicht), ist das dein deutliches Indiz dafür, dass
Polymorphismus beabsichtigt ist. In dem Fall ist es eine extrem gute
Idee, auch einen virtuellen Destruktor zu machen
Karl heinz Buchegger schrieb:> Nennst du 'pure' Functions im Deutschen 'reine' Funktionen?
Nein, das halte ich für eine kranke Eindeutschung.
Genau genommen ist es ja in C++ nur eine etwas schrullige Schreibweise
für eine ABC (abstract base class); letztlich spart man sich mit dem
=0 ein neues Schlüsselwort abstract.
Deshalb erkläre ich im Zweifelsfall erst, was eine ABC ist und wozu
man sie brauchen kann.
Dann kann man kurz erwähnen wie es in anderen Sprachen gehandhabt
wird (Schlüsselwort abstract in Java bspw.) und dann nenne ich
ich einfach die Schreibweise in C++.
Ist dann einfach so und fertig.
Dass man dann eine so deklarierte und mit Absicht nicht definierte
Methode pure virtual nennt, ist nur noch der Name für die
Schreibweise. Das Konzept dahinter ist ABC.
Eindeutschen würde ich das pure virtual nicht.
Und wenn schon, wären es nicht "reine Funktionen", sondern
"rein virtuelle Methoden".
Hallo,
@9:26:
>> Das kann man mit oder ohne virtual, egal wo.>
ja schon aber es gibt noch einen weiteren Unterschied, ohne das virtual
wird immer die zur Compile-Zeit bekannte Methode gerufen, sonst eben die
letzte in der Hierarchie (late binding). Das ist der Vorteil des
Polymorphismus. Die einzige Ausnahme ist der Konstruktur einer
Basisklasse, hier ist es nicht möglich, Methoden abgeleiteter Klassen zu
rufen. Tut man es doch und die Methode der Basis-Klasse ist außerdem
noch 'pure virtual' (... = 0;), gibt es eine Exception (pure virtual
method call).
Ich stelle mir das technisch immer so vor, mit dem virtual wird der
Compiler instruiert, eine Sprungtabelle anzulegen, sobald ein Objekt
einer abgeleiteten Klasse instanziert wird, werden die Einträge mit der
jeweils passenden Signatur mit den Adressen der Methoden in der
abgeleiteten Klasse (so existent) überschrieben.
Gruß
Hermann-Josef
Klaus Wachtler schrieb:> Karl heinz Buchegger schrieb:>> Nennst du 'pure' Functions im Deutschen 'reine' Funktionen?>> Nein, das halte ich für eine kranke Eindeutschung.
Gut das ich nicht alleine bin.
pure und virtual sind nun mal 2 Konzepte die nichts miteinander zu tun
haben, auch wenn sie oft gemeinsam verwendet werden. Die deutsche
Wortschöpfung 'rein virtuell' trägt dem aber nicht Rechnung. 'rein
virtuell' im Gegensatz zu 'irgendwie anders virtuell'.
Der Schlüssel ist das Verständnis, das pure und virtual 2
unterschiedliche Paar Schuhe sind. Deinen Ansatz, die Thematik über den
Begriff der ABC anzugehen finde ich gut.
Karl heinz Buchegger schrieb:> Übrigens: Ein weit verbreiteter Irrtum besteht darin anzunehmen, dass> pure Functions keine Implementierung haben können.>>
1
>classBasis{
2
>public:
3
>virtualintget()=0;
4
>virtualvoidput(int)=0;
5
>};
6
>
7
>intBasis::get()
8
>{
9
>std::cout<<"should not be called, but it is ok for now\n";
10
>return0;
11
>}
12
>
>> Von einer Klasse, die pure Functions enthält und die nicht mit nicht> puren Functions überschrieben wurden, kann kein Objekt erzeugt werden.
Äähhh... das heißt doch aber, dass man eine solche Methode niemals
aufrufen kann, weil man kein Objekt erzeugen kann auf das man sie
anwenden könnte. Wozu ist dann die Implementierung in der abstrakten
Basisklasse gut?
Hm, es sei denn vielleicht es gäbe sowas Kurioses wie eine
static virtual void irgendwas() = 0; Methode...
Man kann für ein Objekt einer abgeleiteten Klasse auch explizit
eine Methode der Basisklasse aufrufen.
Das kann man beispielsweise nutzen, um gemeinsamen Code
dort zu deponieren und z.B. von einer in der Ableitung
re-implementierten Methode aus aufzurufen.
Dazu muß kein Objekt der Basisklasse existieren.
Komplettes Beispiel:
Was ich aber nicht weiß ist: wie bekommt man die Definition von
ABC::tuwas in die Klasse selbst rein (also nicht außerhalb, wie
oben geschrieben sondern innerhalb der class, ähnlich wie
DEF::tuwas())?
Hat da jemand eine Idee?
@Mark
Das eine pure Funktion eine Implementierung haben kann und wozu man
sowas brauchen kann hat Klaus ja schon aufgezeigt.
Aber es geht auch noch viel banaler:
Will man eine Klasse einfach nur pure haben, dann macht man gerne den
Destruktor pure. Aber jede Klasse hat immer einen Destruktor :-)
Klaus Wachtler schrieb:> Was ich aber nicht weiß ist: wie bekommt man die Definition von> ABC::tuwas in die Klasse selbst rein (also nicht außerhalb, wie> oben geschrieben sondern innerhalb der class, ähnlich wie> DEF::tuwas())?
Geht nicht. Steckt als Notiz zwischen zwei Beispielen im Standard
("Note: a function declaration cannot provide both a pure-specifier and
a definition"), ausserdem in der Grammatik-Zusammenfassung im Anhang
ersichtlich.
Karl heinz Buchegger schrieb:> Übrigens: Ein weit verbreiteter Irrtum besteht darin anzunehmen, dass> pure Functions keine Implementierung haben können.
Auch nicht besonders "intuitiv", aber erlaubt: