C++ Polymorphismus mit Beispiel

Was ist Polymorphismus in C++?

In C++, Polymorphismus bewirkt, dass sich eine Mitgliedsfunktion je nach dem Objekt, das sie aufruft, unterschiedlich verhält. Polymorphismus ist ein griechisches Wort, das „viele Formen haben“ bedeutet. Er tritt auf, wenn Sie eine Hierarchie von Klassen haben, die durch Vererbung miteinander verbunden sind.

Angenommen, wir haben die Funktion makeSound(). Wenn eine Katze diese Funktion aufruft, erzeugt sie ein Miaugeräusch. Wenn eine Kuh dieselbe Funktion aufruft, gibt sie das Mähgeräusch von sich.

Polymorphismus in C++

Obwohl wir eine Funktion haben, verhält sie sich unter verschiedenen Umständen unterschiedlich. Die Funktion hat viele Formen; daher haben wir Polymorphismus erreicht.

Arten des Polymorphismus

C++ unterstützt zwei Arten von Polymorphismus:

  • Polymorphismus zur Kompilierungszeit und
  • Laufzeitpolymorphismus.

Arten des Polymorphismus

Kompilierzeitpolymorphismus

Sie rufen die überladenen Funktionen auf, indem Sie die Anzahl und den Typ der Argumente abgleichen. Die Informationen sind während der Kompilierungszeit vorhanden. Das bedeutet, dass die C++ Der Compiler wählt zur Kompilierzeit die richtige Funktion aus.

Polymorphismus zur Kompilierungszeit wird durch Funktions- und Operatorüberladung erreicht.

Funktionsüberlastung

Eine Funktionsüberladung tritt auf, wenn wir viele Funktionen mit ähnlichen Namen, aber unterschiedlichen Argumenten haben. Die Argumente können sich hinsichtlich der Anzahl oder Art unterscheiden.

Beispiel 1

#include <iostream> 
using namespace std;

void test(int i) {
	cout << " The int is " << i << endl;
}
void test(double  f) {
	cout << " The float is " << f << endl;
}
void test(char const *ch) {
	cout << " The char* is " << ch << endl;
}

int main() {
	test(5);
	test(5.5);
	test("five");
	return 0;
}

Ausgang:

Funktionsüberlastung

Hier ist ein Screenshot des Codes:

Funktionsüberlastung

Code-Erklärung:

  1. Fügen Sie die iostream-Header-Datei in unseren Code ein. Wir werden seine Funktionen nutzen können.
  2. Fügen Sie den std-Namespace in unseren Code ein. Wir können seine Klassen verwenden, ohne es aufzurufen.
  3. Erstellen Sie eine Funktion namens test, die einen ganzzahligen Parameter i akzeptiert. Das { markiert den Anfang des Hauptteils des Funktionstests.
  4. Anweisung, die ausgeführt werden soll, wenn der obige Funktionstest aufgerufen/aufgerufen wird.
  5. Ende des Hauptteils des obigen Funktionstests.
  6. Erstellen Sie eine Funktion namens test, die einen Float-Parameter f akzeptiert. Das { markiert den Anfang des Hauptteils des Funktionstests.
  7. Anweisung, die ausgeführt werden soll, wenn der obige Funktionstest aufgerufen/aufgerufen wird.
  8. Ende des Hauptteils des obigen Funktionstests.
  9. Erstellen Sie eine Funktion namens test, die einen Zeichenparameter ch akzeptiert. Das { markiert den Anfang des Hauptteils des Funktionstests.
  10. Anweisung, die ausgeführt werden soll, wenn der obige Funktionstest aufgerufen/aufgerufen wird.
  11. Ende des Hauptteils des obigen Funktionstests.
  12. Rufen Sie die Funktion main() auf. Das { markiert den Anfang des Funktionskörpers.
  13. Rufen Sie den Funktionstest auf und übergeben Sie ihm 5 als Wert des Arguments. Dadurch wird die Testfunktion aufgerufen, die ein ganzzahliges Argument akzeptiert, also die erste Testfunktion.
  14. Rufen Sie den Funktionstest auf und übergeben Sie ihm 5.5 als Wert des Arguments. Dadurch wird die Testfunktion aufgerufen, die ein Float-Argument akzeptiert, also die zweite Testfunktion.
  15. Rufen Sie die Funktion test auf und übergeben Sie ihr fünf als Wert des Arguments. Dadurch wird die Testfunktion aufgerufen, die ein Zeichenargument akzeptiert, also die dritte Testfunktion.
  16. Das Programm muss einen Wert zurückgeben, wenn es erfolgreich ausgeführt wird.
  17. Das Ende des Hauptteils der main()-Funktion.

Wir haben drei Funktionen mit demselben Namen, aber unterschiedlichen Argumenttypen. Wir haben Polymorphismus erreicht.

Operator Überlastung

In Operator Overloading definieren wir eine neue Bedeutung für eine C++ Operator. Es ändert auch die Funktionsweise des Operators. Beispielsweise können wir den Operator + definieren, um zwei Zeichenfolgen zu verketten. Wir kennen ihn als Additionsoperator zum Addieren numerischer Werte. Nach unserer Definition wird er diese addieren, wenn er zwischen Ganzzahlen steht. Wenn er zwischen Zeichenfolgen steht, wird er diese verketten.

Beispiel 2

#include<iostream> 
using namespace std;

class ComplexNum {
private:
	int real, over;
public:
	ComplexNum(int rl = 0, int ov = 0) {
		real = rl;   
		over = ov; 
	}

	ComplexNum operator + (ComplexNum const &obj) {
		ComplexNum result;
		result.real = real + obj.real;
		result.over = over + obj.over;
		return result;
	}
	void print() { 
		cout << real << " + i" << over << endl; 
	}
};
int main()
{
	ComplexNum c1(10, 2), c2(3, 7);
	ComplexNum c3 = c1+c2;
	c3.print();
}

Ausgang:

Operator Überlastung

Hier ist ein Screenshot des Codes:

Operator Überlastung

Operator Überlastung

Code-Erklärung:

  1. Binden Sie die iostream-Header-Datei in unser Programm ein, um dessen Funktionen nutzen zu können.
  2. Fügen Sie den std-Namespace in unser Programm ein, um seine Klassen zu verwenden, ohne ihn aufzurufen.
  3. Erstellen Sie eine Klasse mit dem Namen ComplexNum. Die { markiert den Anfang des Klassenkörpers.
  4. Verwenden Sie den Zugriffsmodifikator „private“, um Variablen als privat zu markieren, was bedeutet, dass auf sie nur innerhalb der Klasse zugegriffen werden kann.
  5. Definieren Sie zwei ganzzahlige Variablen, reell und über.
  6. Verwenden Sie den Zugriffsmodifikator public, um den Konstruktor als öffentlich zu markieren, was bedeutet, dass er auch von außerhalb zugänglich ist Klasse.
  7. Erstellen Sie den Klassenkonstruktor und initialisieren Sie die Variablen.
  8. Initialisieren Sie den Wert der Variablen real.
  9. Initialisieren Sie den Wert der Variablen über.
  10. Ende des Konstruktorkörpers.
  11. Wir müssen die Bedeutung des +-Operators überschreiben.
  12. Erstellen Sie den Datentyp „Ergebnis“ vom Typ „ComplexNum“.
  13. Verwenden Sie den Operator + mit komplexen Zahlen. Diese Zeile addiert den Realteil einer Zahl zum Realteil einer anderen Zahl.
  14. Verwenden Sie den Operator + mit komplexen Zahlen. Diese Zeile addiert den Imaginärteil einer Zahl zum Imaginärteil einer anderen Zahl.
  15. Bei erfolgreicher Ausführung gibt das Programm den Wert der Variablen result zurück.
  16. Ende der Definition der neuen Bedeutung des +-Operators, d. h. Überladung.
  17. Rufen Sie die print()-Methode auf.
  18. Drucken Sie die neue komplexe Zahl nach der Addition auf der Konsole.
  19. Ende des Hauptteils der print()-Funktion.
  20. Ende des Hauptteils der ComplexNum-Klasse.
  21. Rufen Sie die Funktion main() auf.
  22. Übergeben Sie die Werte der zu addierenden reellen und komplexen Teile. Der erste Teil von c1 wird zum ersten Teil von c2 addiert, also 10+3. Der zweite Teil von c1 wird zum zweiten Teil von c addiert, also 2+7.
  23. Führen Sie eine Operation mit dem überladenen +-Operator aus und speichern Sie das Ergebnis in der Variablen c3.
  24. Geben Sie den Wert der Variablen c3 auf der Konsole aus.
  25. Ende des Hauptteils der Funktion main().

Laufzeitpolymorphismus

Dies geschieht, wenn die Methode eines Objekts zur Laufzeit und nicht zur Kompilierungszeit aufgerufen/aufgerufen wird. Laufzeitpolymorphismus wird durch Funktionsüberschreibung erreicht. Die aufzurufende/aufzurufende Funktion wird zur Laufzeit festgelegt.

Funktion überschreiben

Funktionsüberschreibungen treten auf, wenn einer Funktion der Basisklasse eine neue Definition in einer abgeleiteten Klasse gegeben wird. Zu diesem Zeitpunkt können wir sagen, dass die Basisfunktion überschrieben wurde.

Beispielsweise:

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

public:
	void eat() {

		cout << "Mammals eat...";
	}

};

class Cow: public Mammal {

public:
	void eat() {

		cout << "Cows eat grass...";
	}
};
int main(void) {

	Cow c = Cow();

	c.eat();

	return 0;

}

Ausgang:

Funktion überschreiben

Hier ist ein Screenshot des Codes:

Funktion überschreiben

Code-Erklärung:

  1. Importieren Sie die iostream-Header-Datei in unser Programm, um dessen Funktionen zu nutzen.
  2. Fügen Sie den std-Namespace in unser Programm ein, um seine Klassen zu verwenden, ohne ihn aufzurufen.
  3. Erstellen Sie eine Klasse mit dem Namen Mammal. Das { markiert den Anfang des Klassenkörpers.
  4. Verwenden Sie den Modifikator für den öffentlichen Zugriff, um die Funktion, die wir erstellen möchten, als öffentlich zugänglich festzulegen. Es wird von außerhalb dieser Klasse zugänglich sein.
  5. Erstellen Sie eine öffentliche Funktion namens eat. Das { markiert den Anfang des Funktionskörpers.
  6. Gibt die der cout-Funktion hinzugefügte Anweisung aus, wenn die Funktion eat() aufgerufen wird.
  7. Das Ende des Funktionskörpers eat().
  8. Ende des Hauptteils der Klasse Säugetier.
  9. Erstellen Sie eine Klasse mit dem Namen Cow, die die Mammal-Klasse erbt. Cow ist die abgeleitete Klasse, während Mammal die Basisklasse ist. Das { markiert den Anfang dieser Klasse.
  10. Verwenden Sie den Modifikator „public access“, um die Funktion, die wir erstellen möchten, als öffentlich zugänglich zu markieren. Es wird von außerhalb dieser Klasse zugänglich sein.
  11. Überschreiben Sie die Funktion eat(), die in der Basisklasse definiert wurde. Das { markiert den Anfang des Funktionskörpers.
  12. Die Anweisung, die beim Aufruf dieser Funktion auf der Konsole ausgegeben werden soll.
  13. Ende des Hauptteils der Funktion eat().
  14. Ende des Rumpfes der Klasse Cow.
  15. Rufen Sie die Funktion main() auf. Das { markiert den Anfang des Hauptteils dieser Funktion.
  16. Erstellen Sie eine Instanz der Cow-Klasse und geben Sie ihr den Namen c.
  17. Rufen Sie die in der Cow-Klasse definierte Funktion eat() auf.
  18. Das Programm muss bei erfolgreichem Abschluss einen Wert zurückgeben.
  19. Ende der main()-Funktion.

C++ Virtuelle Funktion

Eine virtuelle Funktion ist eine weitere Möglichkeit, Laufzeitpolymorphismus zu implementieren in C++. Es handelt sich um eine spezielle Funktion, die in einer Basisklasse definiert und in der abgeleiteten Klasse neu definiert wird. Um eine virtuelle Funktion zu deklarieren, sollten Sie das Schlüsselwort virtual verwenden. Das Schlüsselwort sollte der Deklaration der Funktion in der Basisklasse vorangehen.

Wenn eine virtuelle Funktionsklasse geerbt wird, definiert die virtuelle Klasse die virtuelle Funktion entsprechend ihren Anforderungen neu. Zum Beispiel:

#include <iostream>  
using namespace std;
class ClassA {
		public:
		virtual void show() {
			cout << "The show() function in base class invoked..." << endl;
		}
	};
	class ClassB :public ClassA {
	public:
		void show() 	{
			cout << "The show() function in derived class invoked...";
		}
	};
	int main() {
		ClassA* a;   
		ClassB b;
		a = &b;
		a->show();      
	}

Ausgang:

C++ Virtuelle Funktion

Hier ist ein Screenshot des Codes:

C++ Virtuelle Funktion

Code-Erklärung:

  1. Fügen Sie die iostream-Headerdatei in den Code ein, um ihre Funktionen zu nutzen.
  2. Fügen Sie den std-Namespace in unseren Code ein, um seine Klassen zu verwenden, ohne ihn aufzurufen.
  3. Erstellen Sie eine Klasse mit dem Namen ClassA.
  4. Verwenden Sie den Modifikator für den öffentlichen Zugriff, um ein Klassenmitglied als öffentlich zugänglich zu markieren.
  5. Erstellen Sie eine virtuelle Funktion namens show(). Es wird eine öffentliche Veranstaltung sein.
  6. Der Text, der gedruckt werden soll, wenn show() aufgerufen wird. Das endl ist ein C++ Schlüsselwort, das Zeilenende bedeutet. Es bewegt den Mauszeiger zur nächsten Zeile.
  7. Ende des Körpers der virtuellen Funktion show().
  8. Ende des Rumpfes der Klasse ClassA.
  9. Erstellen einer neuen Klasse mit dem Namen ClassB, die die Klasse ClassA erbt. KlasseA wird zur Basisklasse, während KlasseB zur abgeleiteten Klasse wird.
  10. Verwenden Sie den Modifikator für den öffentlichen Zugriff, um ein Klassenmitglied als öffentlich zugänglich zu markieren.
  11. Definieren Sie die in der Basisklasse abgeleitete virtuelle Funktion show() neu.
  12. Der Text, der auf der Konsole gedruckt werden soll, wenn die in der abgeleiteten Klasse definierte Funktion show() aufgerufen wird.
  13. Ende des Hauptteils der show()-Funktion.
  14. Ende des Hauptteils der abgeleiteten Klasse, ClassB.
  15. Rufen Sie die Funktion main() auf. Die Programmlogik sollte in den Hauptteil eingefügt werden.
  16. Erstellen Sie eine Zeigervariable mit dem Namen a. Es zeigt auf die Klasse mit dem Namen ClassA.
  17. Erstellen Sie eine Instanz der Klasse mit dem Namen ClassB. Die Instanz erhält den Namen b.
  18. Ordnen Sie die in der Adresse b gespeicherten Werte der Variablen a zu.
  19. Rufen Sie die in der abgeleiteten Klasse definierte Funktion show() auf. Die späte Bindung wurde implementiert.
  20. Ende des Hauptteils der main()-Funktion.

Polymorphismus zur Kompilierungszeit vs. Laufzeitpolymorphismus

Hier sind die Hauptunterschiede zwischen den beiden:

Polymorphismus zur Kompilierungszeit Laufzeitpolymorphismus
Es wird auch frühe Bindung oder statischer Polymorphismus genannt Es wird auch späte/dynamische Bindung oder dynamischer Polymorphismus genannt
Die Methode wird während der Kompilierungszeit aufgerufen/aufgerufen Die Methode wird zur Laufzeit aufgerufen/aufgerufen
Implementiert durch Funktionsüberladung und Operatorüberladung Implementiert über Methodenüberschreibung und virtuelle Funktionen
Beispiel: Methodenüberladung. Viele Methoden haben möglicherweise ähnliche Namen, aber eine unterschiedliche Anzahl oder Art von Argumenten Beispiel: Methodenüberschreibung. Viele Methoden haben möglicherweise einen ähnlichen Namen und denselben Prototyp.
Schnellere Ausführung, da die Methodenerkennung während der Kompilierungszeit erfolgt Langsamere Ausführung, da die Methodenerkennung zur Laufzeit erfolgt.
Less Da zur Kompilierungszeit alles bekannt ist, ist Flexibilität bei der Problemlösung gegeben. Da die Methoden während der Laufzeit ermittelt werden, ist viel Flexibilität beim Lösen komplexer Probleme gegeben.

Zusammenfassung

  • Polymorphismus bedeutet, viele Formen zu haben.
  • Es tritt auf, wenn es eine Hierarchie von Klassen gibt, die durch Vererbung miteinander verbunden sind.
  • Mit Polymorphismus kann sich eine Funktion je nach Objekt, das sie aufruft/aufruft, unterschiedlich verhalten.
  • Beim Polymorphismus zur Kompilierungszeit wird die aufzurufende Funktion während der Kompilierungszeit festgelegt.
  • Beim Laufzeitpolymorphismus wird die aufzurufende Funktion während der Laufzeit festgelegt.
  • Polymorphismus zur Kompilierungszeit wird durch Funktionsüberladung und Operatorüberladung bestimmt.
  • Bei der Funktionsüberladung gibt es viele Funktionen mit ähnlichen Namen, aber unterschiedlichen Argumenten.
  • Die Parameter können sich in Anzahl oder Typ unterscheiden.
  • Bei der Operatorüberladung wird eine neue Bedeutung definiert für C++ durch.
  • Laufzeitpolymorphismus wird durch Funktionsüberschreibung erreicht.
  • Beim Überschreiben von Funktionen gibt eine abgeleitete Klasse einer in der Basisklasse definierten Funktion eine neue Definition.