Virtuell / rein virtuell erklärt

345

Was genau bedeutet es, wenn eine Funktion als virtuell definiert ist und dasselbe wie rein virtuell ist?

Justin
quelle

Antworten:

338

Aus der virtuellen Funktion von Wikipedia ...

Bei der objektorientierten Programmierung in Sprachen wie C ++ und Object Pascal ist eine virtuelle Funktion oder virtuelle Methode eine vererbbare und überschreibbare Funktion oder Methode, für die der dynamische Versand erleichtert wird. Dieses Konzept ist ein wichtiger Bestandteil des (Laufzeit-) Polymorphismus-Teils der objektorientierten Programmierung (OOP). Kurz gesagt, eine virtuelle Funktion definiert eine auszuführende Zielfunktion, aber das Ziel ist zur Kompilierungszeit möglicherweise nicht bekannt.

Im Gegensatz zu einer nicht virtuellen Funktion wird beim Überschreiben einer virtuellen Funktion die am meisten abgeleitete Version auf allen Ebenen der Klassenhierarchie verwendet und nicht nur auf der Ebene, auf der sie erstellt wurde. Wenn daher eine Methode der Basisklasse eine virtuelle Methode aufruft , wird die in der abgeleiteten Klasse definierte Version anstelle der in der Basisklasse definierten Version verwendet.

Dies steht im Gegensatz zu nicht virtuellen Funktionen, die in einer abgeleiteten Klasse weiterhin überschrieben werden können. Die "neue" Version wird jedoch nur von der abgeleiteten Klasse und darunter verwendet, ändert jedoch die Funktionalität der Basisklasse überhaupt nicht.

wohingegen..

Eine rein virtuelle Funktion oder eine rein virtuelle Methode ist eine virtuelle Funktion, die von einer abgeleiteten Klasse implementiert werden muss, wenn die abgeleitete Klasse nicht abstrakt ist.

Wenn eine rein virtuelle Methode vorhanden ist, ist die Klasse "abstrakt" und kann nicht alleine instanziiert werden. Stattdessen muss eine abgeleitete Klasse verwendet werden, die die rein virtuellen Methoden implementiert. Eine reine virtuelle wird überhaupt nicht in der Basisklasse definiert sind , so dass eine abgeleitete Klasse muss es bestimmen, oder dass abgeleitete Klasse ist auch abstrakt und nicht instanziiert werden kann. Nur eine Klasse ohne abstrakte Methoden kann instanziiert werden.

Eine virtuelle bietet eine Möglichkeit, die Funktionalität der Basisklasse zu überschreiben, und eine reine virtuelle erfordert dies.

Diego Dias
quelle
10
Also ... ist rein virtuell ein Schlüsselwort oder nur ein Begriff, der verwendet wird?
Justin
197
virtuelle Leere Funktion () = 0; ist eine reine virtuelle. Das "= 0" zeigt die Reinheit an.
Goz
8
Justin, 'pure virtual' ist nur ein Begriff (kein Schlüsselwort, siehe meine Antwort unten), der bedeutet: "Diese Funktion kann von der Basisklasse nicht implementiert werden. Wie Goz sagte, wird am Ende eines virtuellen" = 0 "hinzugefügt Funktion macht es "rein"
Nick Haddad
14
Ich glaube, Stroustrup sagte, dass er ein pureSchlüsselwort hinzufügen wollte , aber dass Bell Labs im Begriff war, eine Hauptversion von C ++ zu veröffentlichen, und sein Manager würde dies zu diesem späten Zeitpunkt nicht zulassen. Das Hinzufügen von Schlüsselwörtern ist eine große Sache.
Quark
14
Dies ist keine gute Antwort. Jede Methode kann überschrieben werden, nicht nur virtuelle. Siehe meine Antwort für weitere Details.
Asik
212

Ich möchte die Wikipedia-Definition von virtuell kommentieren, die hier von mehreren wiederholt wird. [Zum Zeitpunkt der Erstellung dieser Antwort] definierte Wikipedia eine virtuelle Methode als eine Methode, die in Unterklassen überschrieben werden kann. [Glücklicherweise wurde Wikipedia seitdem bearbeitet und erklärt dies nun korrekt.] Das ist falsch: Jede Methode, nicht nur virtuelle, kann in Unterklassen überschrieben werden. Virtual bietet Ihnen Polymorphismus, dh die Möglichkeit, zur Laufzeit die am häufigsten abgeleitete Überschreibung einer Methode auszuwählen .

Betrachten Sie den folgenden Code:

#include <iostream>
using namespace std;

class Base {
public:
    void NonVirtual() {
        cout << "Base NonVirtual called.\n";
    }
    virtual void Virtual() {
        cout << "Base Virtual called.\n";
    }
};
class Derived : public Base {
public:
    void NonVirtual() {
        cout << "Derived NonVirtual called.\n";
    }
    void Virtual() {
        cout << "Derived Virtual called.\n";
    }
};

int main() {
    Base* bBase = new Base();
    Base* bDerived = new Derived();

    bBase->NonVirtual();
    bBase->Virtual();
    bDerived->NonVirtual();
    bDerived->Virtual();
}

Was ist die Ausgabe dieses Programms?

Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.

Abgeleitet überschreibt jede Methode von Base: nicht nur die virtuelle, sondern auch die nicht virtuelle.

Wir sehen, dass, wenn Sie einen Basiszeiger auf abgeleitet haben (bDerived), der Aufruf von NonVirtual die Implementierung der Basisklasse aufruft. Dies wird zur Kompilierungszeit behoben: Der Compiler erkennt, dass bDerived eine Basis * ist, dass NonVirtual nicht virtuell ist, und führt daher die Auflösung auf Basis der Klasse Base durch.

Beim Aufrufen von Virtual wird jedoch die Implementierung der abgeleiteten Klasse aufgerufen. Aufgrund des Schlüsselworts virtual erfolgt die Auswahl der Methode zur Laufzeit und nicht zur Kompilierungszeit. Was hier zur Kompilierungszeit passiert, ist, dass der Compiler erkennt, dass dies eine Base * ist und dass er eine virtuelle Methode aufruft, sodass er anstelle der Klasse Base einen Aufruf an die vtable einfügt. Diese vtable wird zur Laufzeit instanziiert, daher die Laufzeitauflösung für die am meisten abgeleitete Überschreibung.

Ich hoffe das war nicht zu verwirrend. Kurz gesagt, jede Methode kann überschrieben werden, aber nur virtuelle Methoden bieten Polymorphismus, dh Laufzeitauswahl der am meisten abgeleiteten Überschreibung. In der Praxis wird das Überschreiben einer nicht virtuellen Methode jedoch als schlechte Praxis angesehen und nur selten verwendet. Daher denken viele Leute (einschließlich derjenigen, die diesen Wikipedia-Artikel geschrieben haben), dass nur virtuelle Methoden überschrieben werden können.

Asik
quelle
6
Nur weil der Wikipedia-Artikel (den ich auf keinen Fall verteidige) eine virtuelle Methode definiert "als eine, die in Unterklassen überschrieben werden kann", schließt dies nicht die Möglichkeit aus, dass andere, nicht virtuelle Methoden mit demselben Namen deklariert werden können. Dies wird als Überlastung bezeichnet.
26
Die Definition ist dennoch falsch. Eine Methode, die in einer abgeleiteten Klasse überschrieben werden kann, ist per Definition nicht virtuell. Ob die Methode überschrieben werden kann, spielt für die Definition von "virtuell" keine Rolle. Außerdem bezieht sich "Überladen" normalerweise darauf, dass mehrere Methoden mit demselben Namen und Rückgabetyp, aber unterschiedlichen Argumenten in derselben Klasse vorhanden sind. Es unterscheidet sich stark von "Überschreiben", das genau dieselbe Signatur impliziert, jedoch in einer abgeleiteten Klasse. Wenn es nicht polymorph (nicht virtuelle Basis) gemacht wird, wird es oft als "Verstecken" bezeichnet.
Asik
5
Dies sollte die akzeptierte Antwort sein. Dieser spezielle Wikipedia-Artikel , den ich mir die Zeit nehmen werde, um ihn hier zu verlinken, da es sonst niemand in dieser Frage getan hat , ist völliger Müll. +1, guter Herr.
Josaphatv
2
Jetzt macht es Sinn. Vielen Dank, guter Herr, dass Sie richtig erklärt haben, dass jede Methode von abgeleiteten Klassen überschrieben werden kann. Die Änderung betrifft das Verhalten des Compilers bei der Auswahl der Funktion, die in verschiedenen Situationen aufgerufen wird.
Doodad
3
Es kann hilfreich sein, einen Derived*mit denselben Funktionsaufrufen hinzuzufügen , um den Punkt nach Hause zu fahren. Ansonsten tolle Antwort
Jeff Jones
114

Das virtuelle Schlüsselwort gibt C ++ die Möglichkeit, Polymorphismus zu unterstützen. Wenn Sie einen Zeiger auf ein Objekt einer Klasse haben, z.

class Animal
{
  public:
    virtual int GetNumberOfLegs() = 0;
};

class Duck : public Animal
{
  public:
     int GetNumberOfLegs() { return 2; }
};

class Horse : public Animal
{
  public:
     int GetNumberOfLegs() { return 4; }
};

void SomeFunction(Animal * pAnimal)
{
  cout << pAnimal->GetNumberOfLegs();
}

In diesem (albernen) Beispiel gibt die Funktion GetNumberOfLegs () die entsprechende Nummer zurück, die auf der Klasse des Objekts basiert, für das sie aufgerufen wird.

Betrachten Sie nun die Funktion 'SomeFunction'. Es ist egal, welche Art von Tierobjekt an es übergeben wird, solange es von Animal abgeleitet ist. Der Compiler wandelt jede von Tieren abgeleitete Klasse automatisch in ein Tier um, da es sich um eine Basisklasse handelt.

Wenn wir das tun:

Duck d;
SomeFunction(&d);

es würde '2' ausgeben. Wenn wir das tun:

Horse h;
SomeFunction(&h);

es würde '4' ausgeben. Das können wir nicht machen:

Animal a;
SomeFunction(&a);

weil es nicht kompiliert werden kann, weil die virtuelle Funktion GetNumberOfLegs () rein ist, was bedeutet, dass es durch Ableiten von Klassen (Unterklassen) implementiert werden muss.

Reine virtuelle Funktionen werden hauptsächlich verwendet, um Folgendes zu definieren:

a) abstrakte Klassen

Dies sind Basisklassen, von denen Sie ableiten und dann die reinen virtuellen Funktionen implementieren müssen.

b) Schnittstellen

Dies sind 'leere' Klassen, in denen alle Funktionen rein virtuell sind und Sie daher alle Funktionen ableiten und dann implementieren müssen.

JBRWilkinson
quelle
In Ihrem Beispiel können Sie # 4 nicht ausführen, da Sie keine Implementierung der rein virtuellen Methode bereitgestellt haben. Dies liegt nicht ausschließlich daran, dass die Methode rein virtuell ist.
Iheanyi
@iheanyi Sie können keine Implementierung für eine reine virtuelle Methode in der Basisklasse bereitstellen. Daher ist Fall 4 immer noch ein Fehler.
Prasad
32

In einer C ++ - Klasse ist virtual das Schlüsselwort, das angibt, dass eine Methode von einer Unterklasse überschrieben (dh implementiert) werden kann. Zum Beispiel:

class Shape 
{
  public:
    Shape();
    virtual ~Shape();

    std::string getName() // not overridable
    {
      return m_name;
    }

    void setName( const std::string& name ) // not overridable
    {
      m_name = name;
    }

  protected:
    virtual void initShape() // overridable
    {
      setName("Generic Shape");
    }

  private:
    std::string m_name;
};

In diesem Fall kann eine Unterklasse die initShape- Funktion überschreiben , um spezielle Arbeiten auszuführen :

class Square : public Shape
{
  public: 
    Square();
    virtual ~Square();

  protected:
    virtual void initShape() // override the Shape::initShape function
    {
      setName("Square");
    }
}

Der Begriff " rein virtuell" bezieht sich auf virtuelle Funktionen, die von einer Unterklasse implementiert werden müssen und von der Basisklasse nicht implementiert wurden. Sie legen eine Methode als rein virtuell fest, indem Sie das Schlüsselwort virtual verwenden und am Ende der Methodendeklaration a = 0 hinzufügen .

Wenn Sie Shape :: initShape rein virtuell machen möchten, gehen Sie wie folgt vor:

class Shape 
{
 ...
    virtual void initShape() = 0; // pure virtual method
 ... 
};

Indem Sie Ihrer Klasse eine rein virtuelle Methode hinzufügen, machen Sie die Klasse zu einer abstrakten Basisklasse, die sehr praktisch ist, um Schnittstellen von der Implementierung zu trennen.

Nick Haddad
quelle
1
In Bezug auf "virtuelle Funktionen, die von einer Unterklasse implementiert werden müssen" - das ist nicht unbedingt richtig, aber die Unterklasse ist auch abstrakt, wenn dies nicht der Fall ist. Und abstrakte Klassen können nicht instanziiert werden. Auch "kann nicht von der Basisklasse implementiert werden" scheint irreführend; Ich würde vorschlagen, dass "nicht gewesen" besser wäre, da es keine Einschränkung für Änderungen des Codes gibt, um eine Implementierung innerhalb der Basisklasse hinzuzufügen.
NVRAM
2
Und "die getName-Funktion kann nicht von einer Unterklasse implementiert werden" ist nicht ganz richtig. Unterklassen können die Methode implementieren (mit derselben oder einer anderen Signatur), aber diese Implementierung überschreibt die Methode nicht. Sie können Circle als Unterklasse implementieren und "std :: string Circle :: getName ()" implementieren - dann können Sie eine der beiden Methoden für eine Circle-Instanz aufrufen. Bei Verwendung über einen Shape-Zeiger oder eine Referenz würde der Compiler jedoch Shape :: getName () aufrufen.
NVRAM
1
Gute Punkte an beiden Fronten. Ich habe versucht, mich von der Erörterung von Sonderfällen für dieses Beispiel fernzuhalten. Ich werde die Antwort so ändern, dass sie verzeihender ist. Vielen Dank!
Nick Haddad
@ NickHaddad Alter Thread, aber ich frage mich, warum Sie Ihre Variable aufgerufen haben m_name. Was bedeutet das m_?
Tqn
1
@Tqn unter der Annahme, dass NickHaddad Konventionen befolgt hat, ist m_name eine Namenskonvention, die allgemein als ungarische Notation bezeichnet wird. Das m gibt ein Mitglied einer Struktur / Klasse an, eine Ganzzahl.
Ketcomp
16

"Virtuell" bedeutet, dass die Methode in Unterklassen überschrieben werden kann, jedoch eine direkt aufrufbare Implementierung in der Basisklasse hat. "Rein virtuell" bedeutet, dass es sich um eine virtuelle Methode ohne direkt aufrufbare Implementierung handelt. Eine solche Methode muss mindestens einmal in der Vererbungshierarchie überschrieben werden. Wenn eine Klasse über nicht implementierte virtuelle Methoden verfügt, können Objekte dieser Klasse nicht erstellt werden und die Kompilierung schlägt fehl.

@quark weist darauf hin, dass rein virtuelle Methoden kann eine Implementierung, sondern als reine virtuelle Methoden außer Kraft gesetzt werden muss, kann die Standardimplementierung nicht direkt aufgerufen werden. Hier ist ein Beispiel für eine rein virtuelle Methode mit einer Standardeinstellung:

#include <cstdio>

class A {
public:
    virtual void Hello() = 0;
};

void A::Hello() {
    printf("A::Hello\n");
}

class B : public A {
public:
    void Hello() {
        printf("B::Hello\n");
        A::Hello();
    }
};

int main() {
    /* Prints:
           B::Hello
           A::Hello
    */
    B b;
    b.Hello();
    return 0;
}

Laut Kommentaren ist es compilerspezifisch, ob die Kompilierung fehlschlägt oder nicht. Zumindest in GCC 4.3.3 wird es nicht kompiliert:

class A {
public:
    virtual void Hello() = 0;
};

int main()
{
    A a;
    return 0;
}

Ausgabe:

$ g++ -c virt.cpp 
virt.cpp: In function int main()’:
virt.cpp:8: error: cannot declare variable a to be of abstract type A
virt.cpp:1: note:   because the following virtual functions are pure within A’:
virt.cpp:3: note:   virtual void A::Hello()
John Millikin
quelle
Es muss überschrieben werden, wenn Sie eine Instanz der Klasse instanziieren möchten. Wenn Sie keine Instanzen erstellen, wird der Code problemlos kompiliert.
Glen
1
Die Kompilierung wird nicht fehlschlagen. Wenn keine (reine) virtuelle Methode implementiert ist, kann diese Klasse / dieses Objekt nicht instanziiert werden. Es kann nicht LINK, aber es wird kompiliert.
Tim
@Glen, @tim: Auf welchem ​​Compiler? Wenn ich versuche, ein Programm zu kompilieren, das eine abstrakte Klasse erstellt, wird es nicht kompiliert.
John Millikin
Die @ John-Kompilierung schlägt nur fehl, wenn Sie versuchen, eine Instanz einer Klasse zu instanziieren, die eine PVF enthält. Sie können natürlich Zeiger- oder Referenzwerte für solche Klassen instanziieren.
5
Außerdem, John, ist Folgendes nicht ganz richtig: "'Rein virtuell' bedeutet, dass es sich um eine virtuelle Methode ohne Implementierung handelt." Reine virtuelle Methoden können Implementierungen haben. Sie können sie jedoch nicht direkt aufrufen: Sie müssen die Basisklassenimplementierung innerhalb der Unterklasse überschreiben und verwenden. Auf diese Weise können Sie einen Standardteil der Implementierung bereitstellen. Es ist jedoch keine übliche Technik.
Quark
9

Wie funktioniert das virtuelle Schlüsselwort?

Angenommen, der Mensch ist eine Basisklasse, der Inder ist vom Menschen abgeleitet.

Class Man
{
 public: 
   virtual void do_work()
   {}
}

Class Indian : public Man
{
 public: 
   void do_work()
   {}
}

Das Deklarieren von do_work () als virtuell bedeutet einfach: Welches do_work () aufgerufen werden soll, wird NUR zur Laufzeit bestimmt.

Angenommen, ich tue,

Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.

Wenn virtual nicht verwendet wird, wird dies vom Compiler statisch bestimmt oder statisch gebunden, je nachdem, welches Objekt aufgerufen wird. Wenn also ein Objekt des Menschen do_work () aufruft, heißt das do_work () des Menschen AUCH, obwohl es auf ein indisches Objekt verweist

Ich glaube, dass die am häufigsten gewählte Antwort irreführend ist - Jede Methode, ob virtuell oder nicht, kann eine überschriebene Implementierung in der abgeleiteten Klasse haben. Unter besonderer Bezugnahme auf C ++ ist der korrekte Unterschied die Laufzeitbindung (wenn virtuell verwendet wird) und die Kompilierungszeit (wenn virtuell nicht verwendet wird, aber eine Methode überschrieben wird und ein Basiszeiger auf ein abgeleitetes Objekt zeigt) Bindung der zugehörigen Funktionen.

Es scheint einen weiteren irreführenden Kommentar zu geben, der besagt:

"Justin, 'pure virtual' ist nur ein Begriff (kein Schlüsselwort, siehe meine Antwort unten), der bedeutet:" Diese Funktion kann von der Basisklasse nicht implementiert werden. "

DAS IST FALSCH! Rein virtuelle Funktionen können auch einen Körper haben UND IMPLEMENTIERT WERDEN! Die Wahrheit ist, dass die reine virtuelle Funktion einer abstrakten Klasse statisch aufgerufen werden kann! Zwei sehr gute Autoren sind Bjarne Stroustrup und Stan Lippman ... weil sie die Sprache geschrieben haben.

McMurdo
quelle
2
Unglücklicherweise werden alle anderen ignoriert, sobald eine Antwort positiv bewertet wird. Auch wenn sie besser sein könnten.
LtWorf
3

Eine virtuelle Funktion ist eine Mitgliedsfunktion, die in einer Basisklasse deklariert und von einer abgeleiteten Klasse neu definiert wird. Virtuelle Funktionen sind in der Reihenfolge ihrer Vererbung hierarchisch. Wenn eine abgeleitete Klasse eine virtuelle Funktion nicht überschreibt, wird die in ihrer Basisklasse definierte Funktion verwendet.

Eine reine virtuelle Funktion enthält keine Definition in Bezug auf die Basisklasse. Es hat keine Implementierung in der Basisklasse. Jede abgeleitete Klasse muss diese Funktion überschreiben.

Hautausschläge
quelle
2

In Simula, C ++ und C #, die standardmäßig statische Methodenbindungen verwenden, kann der Programmierer festlegen, dass bestimmte Methoden dynamische Bindungen verwenden sollen, indem sie sie als virtuell kennzeichnen. Die dynamische Methodenbindung ist für die objektorientierte Programmierung von zentraler Bedeutung.

Objektorientierte Programmierung erfordert drei grundlegende Konzepte: Kapselung, Vererbung und dynamische Methodenbindung.

Durch die Kapselung können die Implementierungsdetails einer Abstraktion hinter einer einfachen Schnittstelle verborgen werden.

Durch Vererbung kann eine neue Abstraktion als Erweiterung oder Verfeinerung einer vorhandenen Abstraktion definiert werden, wobei einige oder alle ihrer Merkmale automatisch erhalten werden.

Durch die dynamische Methodenbindung kann die neue Abstraktion ihr neues Verhalten auch dann anzeigen, wenn sie in einem Kontext verwendet wird, der die alte Abstraktion erwartet.

PJT
quelle
1

Virtuelle Methoden können durch Ableiten von Klassen überschrieben werden, benötigen jedoch eine Implementierung in der Basisklasse (die überschrieben wird).

Reine virtuelle Methoden haben keine Implementierung der Basisklasse. Sie müssen durch abgeleitete Klassen definiert werden. (Technisch überschrieben ist also nicht der richtige Begriff, da es nichts zu überschreiben gibt).

Virtual entspricht dem Standardverhalten von Java, wenn die abgeleitete Klasse eine Methode der Basisklasse überschreibt.

Reine virtuelle Methoden entsprechen dem Verhalten abstrakter Methoden innerhalb abstrakter Klassen. Und eine Klasse, die nur reine virtuelle Methoden und Konstanten enthält, wäre das cpp-Pendant zu einer Schnittstelle.

johannes_lalala
quelle
0

Reine virtuelle Funktion

Versuchen Sie diesen Code

#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{

public:

    virtual void sayHellow()=0;

};

class anotherClass:aClassWithPureVirtualFunction
{

public:

    void sayHellow()
    {

        cout<<"hellow World";
    }

};
int main()
{
    //aClassWithPureVirtualFunction virtualObject;
    /*
     This not possible to create object of a class that contain pure virtual function
    */
    anotherClass object;
    object.sayHellow();
}

Entfernen Sie in der Klasse anotherClass die Funktion sayHellow und führen Sie den Code aus. Sie erhalten eine Fehlermeldung! Wenn eine Klasse eine reine virtuelle Funktion enthält, kann kein Objekt aus dieser Klasse erstellt werden und es wird geerbt, dann muss ihre abgeleitete Klasse diese Funktion implementieren.

Virtuelle Funktion

versuchen Sie es mit einem anderen Code

#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{

public:

    virtual void sayHellow()
    {
        cout<<"from base\n";
    }

};

class anotherClass:public aClassWithPureVirtualFunction
{

public:

    void sayHellow()
    {

        cout<<"from derived \n";
    }

};
int main()
{
    aClassWithPureVirtualFunction *baseObject=new aClassWithPureVirtualFunction;
    baseObject->sayHellow();///call base one

    baseObject=new anotherClass;
    baseObject->sayHellow();////call the derived one!

}

Hier wird die Funktion sayHellow in der Basisklasse als virtuell markiert. Dies ist der Compiler, der versucht, die Funktion in der abgeleiteten Klasse zu durchsuchen und die Funktion zu implementieren. Wenn sie nicht gefunden wird, führen Sie die Basisfunktion aus. Danke

Tunvir Rahman Tusher
quelle
Haha, ich habe lange 30 Sekunden gebraucht, um zu verstehen, was hier falsch ist ... Hallo :)
Hans
0

"Eine virtuelle Funktion oder virtuelle Methode ist eine Funktion oder Methode, deren Verhalten innerhalb einer ererbenden Klasse von einer Funktion mit derselben Signatur überschrieben werden kann" - Wikipedia

Dies ist keine gute Erklärung für virtuelle Funktionen. Denn selbst wenn ein Mitglied nicht virtuell ist, kann das Erben von Klassen es überschreiben. Sie können versuchen, es selbst zu sehen.

Der Unterschied zeigt sich, wenn eine Funktion eine Basisklasse als Parameter verwendet. Wenn Sie eine erbende Klasse als Eingabe angeben, verwendet diese Funktion die Basisklassenimplementierung der Überschreibungsfunktion. Wenn diese Funktion jedoch virtuell ist, wird die in der Ableitungsklasse implementierte verwendet.

kann
quelle
0
  • Virtuelle Funktionen müssen eine Definition in der Basisklasse und auch in der abgeleiteten Klasse haben, sind jedoch nicht erforderlich. Beispielsweise ist die Funktion ToString () oder toString () eine virtuelle Funktion, sodass Sie Ihre eigene Implementierung bereitstellen können, indem Sie sie in benutzerdefinierten Klassen überschreiben.

  • Virtuelle Funktionen werden in der normalen Klasse deklariert und definiert.

  • Die reine virtuelle Funktion muss mit "= 0" deklariert werden und kann nur in der abstrakten Klasse deklariert werden.

  • Eine abstrakte Klasse mit einer reinen virtuellen Funktion (en) kann keine Definition (en) dieser reinen virtuellen Funktionen haben. Dies bedeutet, dass die Implementierung in Klassen bereitgestellt werden muss, die von dieser abstrakten Klasse abgeleitet sind.

Sohail xIN3N
quelle
Gleicher Hinweis zu @rashedcs: In der Tat kann eine reine virtuelle Funktion ihre Definition haben ...
Jarek C