C++ Polimorfizam s primjerom

⚡ Pametni sažetak

Polimorfizam u C++ omogućuje jednoj funkciji članici da poprimi mnogo oblika, ponašajući se različito ovisno o objektu koji je poziva. Temelji se na nasljeđivanju i pojavljuje se u dva oblika, rješava se ili tijekom kompajliranja ili tijekom izvođenja.

  • 🔷 Definicija: Polimorfizam znači „mnogo oblika“, što omogućuje jednoj funkciji članici da se ponaša drugačije ovisno o pozivajućem objektu.
  • 🧭 Dvije vrste: C++ pruža polimorfizam za vrijeme kompajliranja (statički) i polimorfizam za vrijeme izvođenja (dinamički).
  • 🧩 Vrijeme kompajliranja: Preopterećenje funkcija i preopterećenje operatora odabiru ispravnu funkciju tijekom kompajliranja.
  • 🔁 Vrijeme provedeno: Nadjačavanje funkcija i virtualne funkcije rješavaju poziv dok se program izvršava.
  • Virtualne funkcije: Ključna riječ virtual u osnovnoj klasi omogućuje kasno vezanje putem pokazivača osnovne klase.
  • 🤖 AI pomoć: GitHub Copilot i slični asistenti izrađuju preopterećene, nadjačane i virtualne funkcije iz kratkog komentara.

C++ polimorfizam

U čemu je polimorfizam C++?

In C++, polimorfizam uzrokuje da se funkcija članica ponaša drugačije ovisno o objektu koji je poziva. Polimorfizam je grčka riječ koja znači imati mnogo oblika. Do njega dolazi kada imate hijerarhiju Nastava povezani putem nasljeđivanja.

Na primjer, pretpostavimo da imamo funkciju makeSound(). Kada mačka pozove ovu funkciju, proizvest će zvuk mijaukanja. Kada krava pozove istu funkciju, proizvest će zvuk miukanja.

Polimorfizam u C++ primjer makeSound

Iako imamo jednu funkciju, ona se ponaša drugačije u različitim okolnostima. Funkcija ima mnogo oblika; dakle, postigli smo polimorfizam.

S osnovnom idejom na mjestu, C++ organizira ovo ponašanje u dvije različite kategorije.

Vrste polimorfizma

C++ podržava dvije vrste polimorfizma:

  • Polimorfizam u vrijeme kompajliranja, i
  • Polimorfizam vremena izvođenja.

Vrste polimorfizma u C++

Prva kategorija rješava svaki poziv funkcije prije nego što se program uopće pokrene.

Polimorfizam vremena kompajliranja

Preopterećene funkcije pozivate podudaranjem broja i vrste argumenata. Informacije su prisutne tijekom vremena kompajliranja. Ovo znači C++ kompajler će odabrati pravu funkciju tijekom kompajliranja.

Polimorfizam u vrijeme prevođenja postiže se preopterećenjem funkcija i preopterećenjem operatora.

Preopterećenje funkcija

Preopterećenje funkcija događa se kada imamo mnogo funkcija sa sličnim imenima, ali različitim argumentima. Argumenti se mogu razlikovati po broju ili vrsti.

Primjer 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;
}

Izlaz:

C++ preopterećenje funkcije Primjer 1 izlaz

Evo snimke zaslona koda:

C++ preopterećenje funkcije Primjer 1 koda

Code Objašnjenje:

  1. Uključite iostream datoteku zaglavlja u naš kod. Moći ćemo koristiti njegove funkcije.
  2. Uključite prostor imena std u naš kod. Moći ćemo koristiti njegove klase bez pozivanja.
  3. Napravite funkciju pod nazivom test koja uzima cjelobrojni parametar i. { označava početak tijela testa funkcije.
  4. Naredba koja će se izvršiti ako se dozove/pozove gornji test funkcije.
  5. Kraj tijela gornjeg testa funkcije.
  6. Napravite funkciju pod nazivom test koja uzima float parametar f. { označava početak tijela testa funkcije.
  7. Naredba koja će se izvršiti ako se dozove/pozove gornji test funkcije.
  8. Kraj tijela gornjeg testa funkcije.
  9. Napravite funkciju pod nazivom test koja uzima karakterni parametar ch. { označava početak tijela testa funkcije.
  10. Naredba koja će se izvršiti ako se dozove/pozove gornji test funkcije.
  11. Kraj tijela gornjeg testa funkcije.
  12. Pozovite funkciju main(). { označava početak tijela funkcije.
  13. Pozovite test funkcije i proslijedite mu 5 kao vrijednost argumenta. Time se poziva testna funkcija koja prihvaća cjelobrojni argument, to jest prva testna funkcija.
  14. Pozovite test funkcije i proslijedite mu 5.5 kao vrijednost argumenta. Ovo će pozvati testnu funkciju koja prihvaća argument float, to jest drugu testnu funkciju.
  15. Pozovite test funkcije i proslijedite mu pet kao vrijednost argumenta. Ovo će pozvati testnu funkciju koja prihvaća znakovni argument, odnosno treću testnu funkciju.
  16. Program mora vratiti vrijednost ako se uspješno izvodi.
  17. Kraj tijela funkcije main().

Imamo tri funkcije s istim imenom, ali različitim vrstama argumenata. Postigli smo polimorfizam.

Operator Preopterećenje

In Operaza preopterećenje, definiramo novo značenje za a C++ operaterTakođer mijenja način rada operatora. Na primjer, možemo definirati operator + za spajanje dvaju nizova. Poznat je kao operator zbrajanja za zbrajanje numeričkih vrijednosti. Nakon naše definicije, kada se postavi između cijelih brojeva, zbrajat će ih. Kada se postavi između nizova, spojit će ih.

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

Izlaz:

C++ preopterećenje operatora Primjer 2 izlaz

Evo snimke zaslona koda:

C++ preopterećenje operatora Primjer 2 koda

C++ preopterećenje operatora rezultat primjera 2

Code Objašnjenje:

  1. Uključite datoteku zaglavlja iostream u naš program kako biste koristili njegove funkcije.
  2. Uključite prostor imena std u naš program kako biste koristili njegove klase bez pozivanja.
  3. Napravite klasu pod nazivom ComplexNum. { označava početak tijela klase.
  4. Koristite modifikator privatnog pristupa za označavanje varijabli kao privatnih, što znači da im se može pristupiti samo iz klase.
  5. Definirajte dvije cjelobrojne varijable, real i over.
  6. Upotrijebite modifikator javnog pristupa kako biste konstruktor označili kao javni, što znači da će biti dostupan čak i izvan klase.
  7. Napravite konstruktor klase i inicijalizirajte varijable.
  8. Inicijalizirajte vrijednost varijable real.
  9. Inicijalizirajte vrijednost varijable preko.
  10. Kraj tijela konstruktora.
  11. Moramo nadjačati značenje operatora +.
  12. Stvorite rezultat tipa podataka tipa ComplexNum.
  13. Koristite operator + sa složenim brojevima. Ovaj redak će dodati realni dio broja realnom dijelu drugog broja.
  14. Koristite operator + sa složenim brojevima. Ova linija će dodati imaginarni dio broja imaginarnom dijelu drugog broja.
  15. Program će vratiti vrijednost varijable rezultat nakon uspješnog izvođenja.
  16. Kraj definicije novog značenja + operatora, odnosno preopterećenja.
  17. Pozovite metodu print().
  18. Ispišite novi kompleksni broj nakon zbrajanja na konzoli.
  19. Kraj tijela print() funkcije.
  20. Kraj tijela klase ComplexNum.
  21. Pozovite funkciju main().
  22. Proslijedite vrijednosti i stvarnih i složenih dijelova koje treba dodati. Prvi dio od c1 će se dodati prvom dijelu od c2, to jest, 10+3. Drugi dio od c1 će se dodati drugom dijelu od c, to jest, 2+7.
  23. Izvedite operaciju koristeći preopterećeni operator + i pohranjujući rezultat u varijablu c3.
  24. Ispišite vrijednost varijable c3 na konzoli.
  25. Kraj tijela funkcije main().

Dok polimorfizam u vrijeme kompajliranja odlučuje rano, druga kategorija odgađa izbor do izvršenja.

Runtime polimorfizam

To se događa kada se metoda objekta dozove/pozove tijekom vremena izvođenja umjesto tijekom vremena kompajliranja. Polimorfizam vremena izvođenja postiže se nadjačavanjem funkcija. Funkcija koja se poziva/poziva uspostavlja se tijekom izvođenja.

Nadjačavanje funkcije

Nadjačavanje funkcije događa se kada funkcija osnovne klase dobije novu definiciju u izvedenoj klasi. U to vrijeme možemo reći da je osnovna funkcija nadjačana.

Na primjer:

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

}

Izlaz:

C++ funkcija koja nadjačava izlaz

Evo snimke zaslona koda:

C++ kod za nadjačavanje funkcije

Code Objašnjenje:

  1. Uvezite iostream datoteku zaglavlja u naš program da biste koristili njegove funkcije.
  2. Uključite prostor imena std u naš program kako biste koristili njegove klase bez pozivanja.
  3. Napravite klasu pod nazivom Mammal. { označava početak tijela klase.
  4. Upotrijebite modifikator javnog pristupa da postavite funkciju koju ćemo izraditi kao javno dostupnu. Bit će mu dostupno izvan ove klase.
  5. Stvorite javnu funkciju pod nazivom jesti. { označava početak tijela funkcije.
  6. Ispišite naredbu dodanu funkciji cout kada se pozove funkcija eat().
  7. Kraj tijela funkcije eat().
  8. Kraj tijela klase sisavaca.
  9. Napravite klasu pod nazivom Krava koja nasljeđuje klasu Sisavac. Krava je izvedena klasa, dok je sisavac osnovna klasa. { označava početak ove klase.
  10. Upotrijebite modifikator javnog pristupa da označite funkciju koju ćemo izraditi kao javno dostupnu. Bit će mu dostupno izvan ove klase.
  11. Nadjačajte funkciju eat() koja je definirana u osnovnoj klasi. { označava početak tijela funkcije.
  12. Naredba za ispis na konzoli kada se ova funkcija pozove.
  13. Kraj tijela funkcije eat().
  14. Kraj tijela klase Krava.
  15. Pozovite funkciju main(). { označava početak tijela ove funkcije.
  16. Napravite instancu klase Krava i dajte joj ime c.
  17. Pozovite funkciju eat() definiranu u klasi Cow.
  18. Program mora vratiti vrijednost nakon uspješnog završetka.
  19. Kraj funkcije main().

C++ Virtualna funkcija

Virtualna funkcija je još jedan način implementacije polimorfizma vremena izvođenja u C++. To je posebna funkcija definirana u osnovnoj klasi i redefinirana u izvedenoj klasi. Da biste deklarirali virtualnu funkciju, trebali biste koristiti ključnu riječ virtual. Ključna riječ treba prethoditi deklaraciji funkcije u osnovnoj klasi.

Ako je klasa virtualne funkcije naslijeđena, virtualna klasa redefinira virtualnu funkciju kako bi odgovarala svojim potrebama. Na primjer:

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

Izlaz:

C++ izlaz virtualne funkcije

Evo snimke zaslona koda:

C++ virtualni funkcijski kod

Code Objašnjenje:

  1. Uključite datoteku zaglavlja iostreama u kod da biste koristili njegove funkcije.
  2. Uključite prostor imena std u naš kod da biste koristili njegove klase bez pozivanja.
  3. Napravite klasu pod nazivom ClassA.
  4. Koristite modifikator javnog pristupa da označite člana razreda kao javno dostupnog.
  5. Napravite virtualnu funkciju pod nazivom show(). Bit će to javna funkcija.
  6. Tekst za ispis kada se pozove pozvani show(). Kraj je a C++ ključna riječ, što znači završni redak. Pomiče kursor miša u sljedeći redak.
  7. Kraj tijela virtualne funkcije show().
  8. Kraj tijela klase ClassA.
  9. Stvaranje nove klase pod nazivom ClassB koja nasljeđuje klasu ClassA. ClassA postaje osnovna klasa dok ClassB postaje izvedena klasa.
  10. Koristite modifikator javnog pristupa da označite člana razreda kao javno dostupnog.
  11. Redefinirajte virtualnu funkciju show() izvedenu u osnovnoj klasi.
  12. Tekst za ispis na konzoli kada se pozove funkcija show() definirana u izvedenoj klasi.
  13. Kraj tijela funkcije show().
  14. Kraj tijela izvedene klase, ClassB.
  15. Pozovite funkciju main(). Programsku logiku treba dodati unutar njegovog tijela.
  16. Napravite varijablu pokazivača pod nazivom a. Pokazuje na klasu pod nazivom ClassA.
  17. Napravite instancu klase pod nazivom ClassB. Instanci se daje naziv b.
  18. Varijabli a dodijelite vrijednosti pohranjene na adresi b.
  19. Pozovite funkciju show() definiranu u izvedenoj klasi. Implementirano je kasno vezanje.
  20. Kraj tijela funkcije main().

S obzirom na to da su oba mehanizma obuhvaćena, donja tablica ih uspoređuje.

Polimorfizam u vremenu kompajliranja vs. Polimorfizam u vremenu izvođenja

Evo glavnih razlika između to dvoje:

Polimorfizam kompilacije Polimorfizam u vremenu izvođenja
Također se naziva rano vezanje ili statički polimorfizam Također se naziva kasno/dinamičko vezanje ili dinamički polimorfizam
Metoda se poziva/poziva tijekom vremena prevođenja Metoda se poziva/doziva tijekom vremena izvođenja
Implementirano preko preopterećenja funkcija i preopterećenja operatora Implementirano putem nadjačavanja metoda i virtualnih funkcija
Primjer, preopterećenje metode. Mnoge metode mogu imati slična imena, ali različit broj ili vrste argumenata Primjer, nadjačavanje metode. Mnoge metode mogu imati sličan naziv i isti prototip.
Brže izvršavanje jer se otkrivanje metode vrši tijekom vremena kompajliranja Sporije izvršavanje jer se otkrivanje metoda vrši tijekom izvođenja.
Less omogućena je fleksibilnost za rješavanje problema budući da je sve poznato tijekom vremena prevođenja. Omogućena je velika fleksibilnost za rješavanje složenih problema jer se metode otkrivaju tijekom izvođenja.

Pitanja i odgovori

Preopterećenje definira nekoliko funkcija s istim imenom, ali različitim parametrima, što se rješava tijekom kompajliranja bez nasljeđivanja. Nadjačavanje redefinira naslijeđenu funkciju osnovne klase s istim potpisom u izvedenoj klasi, što se rješava tijekom izvođenja kada se funkcija deklarira kao virtualna.

Čista virtualna funkcija deklarirana je s = 0 i nema tijelo u osnovnoj klasi. Bilo koja klasa koja ga sadrži postaje abstract klasu, koja se ne može izravno instancirati i prisiljava izvedene klase da osiguraju vlastitu implementaciju.

Kada klasa deklarira virtualne funkcije, kompajler gradi virtualnu tablicu (vtable) pokazivača funkcija. Svaki objekt pohranjuje skriveni pokazivač na svoju klasu vtable, tako da pokazivač osnovne klase poziva ispravnu nadjačanu funkciju tijekom izvođenja putem kasnog vezanja.

Da. Predlošci omogućuju jednoj funkciji ili klasi rad s više tipova podataka, pri čemu kompajler generira kod specifičan za tip tijekom kompajliranja. Ovo generičko programiranje je oblik statičkog polimorfizma koji nadopunjuje preopterećenje funkcija i preopterećenje operatora.

Kada izbrišete izvedeni objekt putem pokazivača osnovne klase, samo virtualni destruktor jamči da će se i izvedeni destruktor pokrenuti. Bez njega, čišćenje je nepotpuno i uzrokuje curenje memorije. Deklarisanje virtualnog osnovnog destruktora čini da se uništavanje ponaša polimorfno.

Polimorfizam omogućuje jednom sučelju rukovanje mnogim tipovima objekata, smanjujući duplicirani kod i pojednostavljujući održavanje. Podržava fleksibilne, proširive dizajne gdje se nove izvedene klase uključuju bez promjene postojećeg koda i omogućuje moćne obrasce izgrađene na pokazivačima i referencama osnovnih klasa.

Da. AI kodirajući asistenti pretvaraju kratki komentar u preopterećene funkcije, virtualne osnovne klase i izvedena nadjačavanja. Brzo obrađuju ponavljajuće standardne fraze, iako biste i dalje trebali provjeriti virtualne ključne riječi, potpise funkcija i sigurnost destruktora prije kompajliranja generiranog koda.

Da. GitHub kopilot Predlaže deklaracije virtualnih funkcija, nadjačavanja izvedenih klasa i preopterećenja operatora dok tipkate. Ubrzava izradu standardnih hijerarhija nasljeđivanja, iako biste trebali potvrditi ključnu riječ virtualna, odgovarajuće potpise i ispraviti ponašanje kasnog vezanja prije izgradnje.

Sažmite ovu objavu uz: