C++ Polymorfismus s příkladem

V čem je polymorfismus C++?

In C++, polymorfismus způsobuje, že se členská funkce chová odlišně na základě objektu, který ji volá/vyvolá. Polymorfismus je řecké slovo, které znamená mít mnoho podob. Vyskytuje se, když máte hierarchii tříd souvisejících prostřednictvím dědičnosti.

Předpokládejme například, že máme funkci makeSound(). Když kočka zavolá tuto funkci, vydá zvuk mňoukání. Když kráva vyvolá stejnou funkci, vydá zvuk mňoukání.

Polymorfismus v C++

I když máme jednu funkci, chová se za různých okolností jinak. Funkce má mnoho podob; proto jsme dosáhli polymorfismu.

Druhy polymorfismu

C++ podporuje dva typy polymorfismu:

  • Polymorfismus v době kompilace a
  • Runtime polymorfismus.

Druhy polymorfismu

Polymorfismus času kompilace

Přetížené funkce vyvoláte porovnáním počtu a typu argumentů. Informace jsou přítomny během kompilace. To znamená C++ kompilátor vybere správnou funkci v době kompilace.

Polymorfismu v době kompilace je dosaženo přetížením funkcí a přetížením operátorů.

Přetížení funkcí

K přetížení funkcí dochází, když máme mnoho funkcí s podobnými názvy, ale různými argumenty. Argumenty se mohou lišit co do počtu nebo typu.

Příklad 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;
}

Výstup:

Přetížení funkcí

Zde je snímek obrazovky kódu:

Přetížení funkcí

Vysvětlení kódu:

  1. Zahrňte hlavičkový soubor iostream do našeho kódu. Budeme moci využívat jeho funkce.
  2. Zahrňte do našeho kódu jmenný prostor std. Budeme moci používat jeho třídy, aniž bychom ho volali.
  3. Vytvořte funkci s názvem test, která přebírá celočíselný parametr i. { označuje začátek těla funkčního testu.
  4. Příkaz, který se má provést, pokud je vyvolán/volán výše uvedený funkční test.
  5. Konec těla výše uvedeného funkčního testu.
  6. Vytvořte funkci s názvem test, která přebírá plovoucí parametr f. { označuje začátek těla funkčního testu.
  7. Příkaz, který se má provést, pokud je vyvolán/volán výše uvedený funkční test.
  8. Konec těla výše uvedeného funkčního testu.
  9. Vytvořte funkci s názvem test, která přebírá znakový parametr ch. { označuje začátek těla funkčního testu.
  10. Příkaz, který se má provést, pokud je vyvolán/volán výše uvedený funkční test.
  11. Konec těla výše uvedeného funkčního testu.
  12. Zavolejte funkci main(). { označuje začátek těla funkce.
  13. Zavolejte test funkce a předejte mu 5 jako hodnotu argumentu. Tím se vyvolá testovací funkce, která přijímá celočíselný argument, tedy první testovací funkce.
  14. Zavolejte test funkce a předejte mu 5.5 jako hodnotu argumentu. Tím se vyvolá testovací funkce, která přijímá argument float, tedy druhá testovací funkce.
  15. Zavolejte test funkce a předejte mu pět jako hodnotu argumentu. Tím se vyvolá testovací funkce, která přijímá znakový argument, tedy třetí testovací funkce.
  16. Pokud program úspěšně běží, musí vrátit hodnotu.
  17. Konec těla funkce main().

Máme tři funkce se stejným názvem, ale různými typy argumentů. Dosáhli jsme polymorfismu.

Operator Přetížení

In Operator Přetížení definujeme nový význam pro a C++ operátor. Mění se také způsob práce operátora. Můžeme například definovat operátor + pro zřetězení dvou řetězců. Známe jej jako operátor sčítání pro sčítání číselných hodnot. Po naší definici je při umístění mezi celá čísla sečte. Při umístění mezi řetězce je zřetězí.

Příklad 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();
}

Výstup:

Operator Přetížení

Zde je snímek obrazovky kódu:

Operator Přetížení

Operator Přetížení

Vysvětlení kódu:

  1. Zahrňte hlavičkový soubor iostream do našeho programu, abyste mohli používat jeho funkce.
  2. Zahrňte jmenný prostor std do našeho programu, abyste mohli používat jeho třídy bez jeho volání.
  3. Vytvořte třídu s názvem ComplexNum. { označuje začátek těla třídy.
  4. Pomocí modifikátoru private access označte proměnné jako soukromé, což znamená, že k nim lze přistupovat pouze ze třídy.
  5. Definujte dvě celočíselné proměnné, real a over.
  6. Pomocí modifikátoru public access označte konstruktor jako veřejný, což znamená, že bude přístupný i zvenčí třída.
  7. Vytvořte konstruktor třídy a inicializujte proměnné.
  8. Inicializujte hodnotu proměnné real.
  9. Inicializujte hodnotu proměnné přes.
  10. Konec těla konstruktoru.
  11. Musíme přepsat význam operátoru +.
  12. Vytvořte výsledek typu dat typu ComplexNum.
  13. Pro komplexní čísla použijte operátor +. Tento řádek přidá skutečnou část čísla ke skutečné části jiného čísla.
  14. Pro komplexní čísla použijte operátor +. Tento řádek přidá imaginární část čísla k imaginární části jiného čísla.
  15. Po úspěšném provedení program vrátí hodnotu proměnné výsledek.
  16. Konec definice nového významu operátoru +, tedy přetěžování.
  17. Zavolejte metodu print().
  18. Po přidání na konzoli vytiskněte nové komplexní číslo.
  19. Konec těla funkce print().
  20. Konec těla třídy ComplexNum.
  21. Zavolejte funkci main().
  22. Předejte hodnoty skutečných i komplexních částí, které mají být přidány. První část c1 bude přidána k první části c2, tedy 10+3. Druhá část c1 bude přidána k druhé části c, tedy 2+7.
  23. Proveďte operaci pomocí operátoru přetížení + a uložte výsledek do proměnné c3.
  24. Vytiskněte hodnotu proměnné c3 na konzole.
  25. Konec těla funkce main().

Runtime polymorfismus

K tomu dochází, když je metoda objektu vyvolána/volána během běhu, nikoli během kompilace. Polymorfismus za běhu je dosažen přepsáním funkcí. Funkce, která má být volána/vyvolána, je vytvořena za běhu.

Přepsání funkce

K přepsání funkce dochází, když je funkci základní třídy přidělena nová definice v odvozené třídě. V té době můžeme říci, že základní funkce byla přepsána.

Například:

#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;

}

Výstup:

Přepsání funkce

Zde je snímek obrazovky kódu:

Přepsání funkce

Vysvětlení kódu:

  1. Importujte hlavičkový soubor iostream do našeho programu, abyste mohli používat jeho funkce.
  2. Zahrňte jmenný prostor std do našeho programu, abyste mohli používat jeho třídy bez jeho volání.
  3. Vytvořte třídu s názvem Savec. { označuje začátek těla třídy.
  4. Pomocí modifikátoru veřejného přístupu nastavte funkci, kterou se chystáme vytvořit, jako veřejně přístupnou. Bude přístupný mimo tuto třídu.
  5. Vytvořte veřejnou funkci s názvem eat. { označuje začátek těla funkce.
  6. Vytiskněte příkaz přidaný do funkce cout při vyvolání funkce eat().
  7. Konec těla funkce eat().
  8. Konec těla třídy Savec.
  9. Vytvořte třídu s názvem Kráva, která zdědí třídu Savec. Kráva je odvozená třída, zatímco savec je základní třída. { označuje začátek této třídy.
  10. Pomocí modifikátoru veřejného přístupu označte funkci, kterou se chystáme vytvořit, jako veřejně přístupnou. Bude přístupný mimo tuto třídu.
  11. Přepište funkci eat(), která byla definována v základní třídě. { označuje začátek těla funkce.
  12. Příkaz, který se má vytisknout na konzole při vyvolání této funkce.
  13. Konec těla funkce eat().
  14. Konec těla třídy Kráva.
  15. Zavolejte funkci main(). { označuje začátek těla této funkce.
  16. Vytvořte instanci třídy Cow a dejte jí název c.
  17. Zavolejte funkci eat() definovanou ve třídě Cow.
  18. Program musí po úspěšném dokončení vrátit hodnotu.
  19. Konec funkce main().

C++ Virtuální funkce

Virtuální funkce je dalším způsobem implementace polymorfismu za běhu C++. Je to speciální funkce definovaná v základní třídě a předefinovaná v odvozené třídě. Chcete-li deklarovat virtuální funkci, měli byste použít klíčové slovo virtual. Klíčové slovo by mělo předcházet deklaraci funkce v základní třídě.

Pokud je třída virtuální funkce zděděna, virtuální třída předefinuje virtuální funkci tak, aby vyhovovala jejím potřebám. Například:

#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();      
	}

Výstup:

C++ Virtuální funkce

Zde je snímek obrazovky kódu:

C++ Virtuální funkce

Vysvětlení kódu:

  1. Chcete-li používat jeho funkce, zahrňte do kódu soubor záhlaví iostream.
  2. Zahrňte do našeho kódu jmenný prostor std, abyste mohli používat jeho třídy bez jeho volání.
  3. Vytvořte třídu s názvem ClassA.
  4. Pomocí modifikátoru veřejného přístupu označte člena třídy jako veřejně přístupného.
  5. Vytvořte virtuální funkci s názvem show(). Bude to veřejná funkce.
  6. Text, který se má vytisknout, když je vyvolána funkce show(). Konec je a C++ klíčové slovo, což znamená koncový řádek. Přesune kurzor myši na další řádek.
  7. Konec těla virtuální funkce show().
  8. Konec těla třídy ClassA.
  9. Vytvoření nové třídy s názvem ClassB, která dědí třídu ClassA. ClassA se stane základní třídou, zatímco ClassB se stane odvozenou třídou.
  10. Pomocí modifikátoru veřejného přístupu označte člena třídy jako veřejně přístupného.
  11. Předefinujte virtuální funkci show() odvozenou v základní třídě.
  12. Text, který se má vytisknout na konzole, když je vyvolána funkce show() definovaná v odvozené třídě.
  13. Konec těla funkce show().
  14. Konec těla odvozené třídy ClassB.
  15. Zavolejte funkci main(). Logika programu by měla být přidána do jeho těla.
  16. Vytvořte proměnnou ukazatele s názvem a. Ukazuje na třídu s názvem ClassA.
  17. Vytvořte instanci třídy s názvem ClassB. Instance je pojmenována b.
  18. Přiřaďte hodnoty uložené na adrese b v proměnné a.
  19. Vyvolejte funkci show() definovanou v odvozené třídě. Byla implementována pozdní vazba.
  20. Konec těla funkce main().

Polymorfismus v době kompilace vs. Run-time polymorfismus

Zde jsou hlavní rozdíly mezi těmito dvěma:

Polymorfismus kompilace Polymorfismus za běhu
Nazývá se také časná vazba nebo statický polymorfismus Říká se tomu také pozdní/dynamická vazba nebo dynamický polymorfismus
Metoda je volána/vyvolána během kompilace Metoda je volána/vyvolána během běhu
Implementováno přes přetížení funkcí a přetížení obsluhy Implementováno pomocí přepisování metod a virtuálních funkcí
Příklad přetížení metody. Mnoho metod může mít podobné názvy, ale odlišný počet nebo typy argumentů Příklad, přepsání metody. Mnoho metod může mít podobný název a stejný prototyp.
Rychlejší provádění, protože zjišťování metod se provádí během kompilace Pomalejší provádění, protože zjišťování metod se provádí za běhu.
Less flexibilita pro řešení problémů je poskytována, protože vše je známo během kompilace. Při řešení složitých problémů je poskytována velká flexibilita, protože metody jsou objeveny za běhu.

Shrnutí

  • Polymorfismus znamená mít mnoho podob.
  • Vyskytuje se, když existuje hierarchie tříd souvisejících prostřednictvím dědičnosti.
  • S polymorfismem se funkce může chovat odlišně na základě objektu, který ji vyvolává/volá.
  • V polymorfismu v době kompilace je funkce, která má být vyvolána, stanovena během kompilace.
  • V běhovém polymorfismu je funkce, která má být vyvolána, stanovena během běhu.
  • Polymorfismus v době kompilace je určen přetížením funkcí a přetížením operátorů.
  • Při přetěžování funkcí existuje mnoho funkcí s podobnými názvy, ale různými argumenty.
  • Parametry se mohou lišit počtem nebo typem.
  • V přetížení operátora je definován nový význam C++ Operátoři.
  • Polymorfismus za běhu je dosažen přepsáním funkcí.
  • Při přepisování funkcí poskytuje odvozená třída novou definici funkce definované v základní třídě.