C++ Polymorfismi esimerkin kanssa
Mitä polymorfismi sisältää C++?
In C++, polymorfismi saa jäsenfunktion käyttäytymään eri tavalla sen mukaan, mikä sitä kutsuu/kutsua. Polymorfismi on kreikan kielen sana, joka tarkoittaa monia muotoja. Se tapahtuu, kun sinulla on periytymisen kautta liittyvien luokkien hierarkia.
Oletetaan esimerkiksi, että meillä on funktio makeSound(). Kun kissa kutsuu tätä toimintoa, se tuottaa miau-äänen. Kun lehmä käyttää samaa toimintoa, se antaa moow-äänen.
Vaikka meillä on yksi toiminto, se käyttäytyy eri tavalla eri olosuhteissa. Funktiolla on monia muotoja; näin ollen olemme saavuttaneet polymorfismin.
Polymorfismin tyypit
C++ tukee kahden tyyppistä polymorfismia:
- Käännösajan polymorfismi ja
- Ajonaikainen polymorfismi.
Kokoa aikapolymorfismi
Kutsut ylikuormitetut funktiot sovittamalla argumenttien lukumäärän ja tyypin. Tiedot ovat esillä käännösaikana. Tämä tarkoittaa C++ kääntäjä valitsee oikean funktion käännöshetkellä.
Käännösajan polymorfismi saavutetaan toimintojen ylikuormituksella ja operaattorin ylikuormituksella.
Toimintojen ylikuormitus
Funktioiden ylikuormitus tapahtuu, kun meillä on monia funktioita, joilla on samanlaiset nimet, mutta eri argumentit. Argumentit voivat vaihdella lukumäärän tai tyypin suhteen.
Esimerkki 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;
}
lähtö:
Tässä on kuvakaappaus koodista:
Koodin selitys:
- Sisällytä iostream-otsikkotiedosto koodiimme. Pystymme käyttämään sen toimintoja.
- Sisällytä std-nimiavaruus koodiimme. Voimme käyttää sen luokkia soittamatta siihen.
- Luo funktio nimeltä testi, joka ottaa kokonaislukuparametrin i. { merkitsee toimintatestin alkua.
- Suoritettava lauseke, jos yllä oleva toimintotesti vedetään/kutsutaan.
- Yllä olevan toimintatestin rungon loppu.
- Luo funktio nimeltä testi, joka ottaa float-parametrin f. { merkitsee toimintatestin alkua.
- Suoritettava lauseke, jos yllä oleva toimintotesti vedetään/kutsutaan.
- Yllä olevan toimintatestin rungon loppu.
- Luo funktio nimeltä testi, joka ottaa merkkiparametrin ch. { merkitsee toimintatestin alkua.
- Suoritettava lauseke, jos yllä oleva toimintotesti vedetään/kutsutaan.
- Yllä olevan toimintatestin rungon loppu.
- Kutsu main()-funktiota. { merkitsee funktion rungon alkua.
- Kutsu funktio testi ja syötä sille 5 argumentin arvoksi. Tämä käynnistää testifunktion, joka hyväksyy kokonaislukuargumentin, eli ensimmäisen testifunktion.
- Kutsu funktiotesti ja syötä sille 5.5 argumentin arvoksi. Tämä käynnistää testifunktion, joka hyväksyy float-argumentin, eli toisen testifunktion.
- Kutsu funktiotesti ja anna sille argumentin arvoksi viisi. Tämä käynnistää testifunktion, joka hyväksyy merkkiargumentin, eli kolmannen testifunktion.
- Ohjelman on palautettava arvo, jos se toimii onnistuneesti.
- Main()-funktion rungon loppu.
Meillä on kolme funktiota, joilla on sama nimi, mutta erityyppiset argumentit. Olemme saavuttaneet polymorfismin.
Operator Ylikuormitus
In Operator Ylikuormitus, määrittelemme uuden merkityksen a:lle C++ operaattori. Se myös muuttaa tapaa, jolla operaattori toimii. Voimme esimerkiksi määrittää +-operaattorin ketjuttamaan kaksi merkkijonoa. Tunnemme sen summausoperaattorina numeeristen arvojen lisäämiseen. Määritelmämme jälkeen, kun se sijoitetaan kokonaislukujen väliin, se lisää ne. Kun se asetetaan merkkijonojen väliin, se ketjuttaa ne.
Esimerkki 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();
}
lähtö:
Tässä on kuvakaappaus koodista:
Koodin selitys:
- Sisällytä iostream-otsikkotiedosto ohjelmaamme, jotta voit käyttää sen toimintoja.
- Sisällytä std-nimiavaruus ohjelmaamme, jotta voit käyttää sen luokkia kutsumatta sitä.
- Luo luokka nimeltä ComplexNum. { merkitsee luokan rungon alkua.
- Käytä yksityisen käyttöoikeuden muokkaajaa merkitäksesi muuttujat yksityisiksi, mikä tarkoittaa, että niihin pääsee vain luokasta käsin.
- Määritä kaksi kokonaislukumuuttujaa, real ja over.
- Käytä julkisen käyttöoikeuden muokkaajaa merkitsemään rakentaja julkiseksi, mikä tarkoittaa, että se on käytettävissä myös ulkopuolelta luokka.
- Luo luokan konstruktori ja alusta muuttujat.
- Alusta muuttujan real arvo.
- Alusta muuttujan arvo yli.
- Rakentajan rungon loppu.
- Meidän on ohitettava +-operaattorin merkitys.
- Luo tietotyypin tulos, jonka tyyppi on ComplexNum.
- Käytä +-operaattoria kompleksilukujen kanssa. Tämä rivi lisää luvun reaaliosan toisen luvun reaaliosaan.
- Käytä +-operaattoria kompleksilukujen kanssa. Tämä rivi lisää luvun imaginaarisen osan toisen luvun imaginaariseen osaan.
- Ohjelma palauttaa muuttujan tuloksen arvon onnistuneen suorituksen jälkeen.
- + -operaattorin uuden merkityksen, eli ylikuormituksen, määritelmän loppu.
- Kutsu print()-menetelmää.
- Tulosta uusi kompleksiluku lisäyksen jälkeen konsolissa.
- Print()-funktion rungon loppu.
- ComplexNum-luokan rungon loppu.
- Kutsu main()-funktiota.
- Välitä sekä todellisten että monimutkaisten lisättävien osien arvot. C1:n ensimmäinen osa lisätään c2:n ensimmäiseen osaan, eli 10+3. C1:n toinen osa lisätään c:n toiseen osaan, eli 2+7.
- Suorita operaatio overloaded + -operaattorilla ja tallenna tulos muuttujaan c3.
- Tulosta konsoliin muuttujan c3 arvo.
- Main()-funktion rungon loppu.
Suorituksen polymorfismi
Tämä tapahtuu, kun objektin menetelmää kutsutaan/kutsutaan ajon aikana eikä käännösajan aikana. Ajonaikainen polymorfismi saavutetaan funktion ohituksella. Kutsuttava/kutsuttava toiminto määritetään ajon aikana.
Toiminnon ohitus
Funktioiden ohittaminen tapahtuu, kun perusluokan funktiolle annetaan uusi määritelmä johdetussa luokassa. Tuolloin voimme sanoa, että perustoiminto on ohitettu.
Esimerkiksi:
#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;
}
lähtö:
Tässä on kuvakaappaus koodista:
Koodin selitys:
- Tuo iostream-otsikkotiedosto ohjelmaamme käyttääksesi sen toimintoja.
- Sisällytä std-nimiavaruus ohjelmaamme, jotta voit käyttää sen luokkia kutsumatta sitä.
- Luo luokka nimeltä Mammal. { merkitsee luokan rungon alkua.
- Käytä julkisen käyttöoikeuden muokkaajaa asettaaksesi luotavan toiminnon julkisesti käytettäväksi. Se on käytettävissä tämän luokan ulkopuolelta.
- Luo julkinen toiminto nimeltä eat. { merkitsee funktion rungon alkua.
- Tulosta cout-funktioon lisätty käsky, kun funktio eat() kutsutaan.
- Toiminnon eat() rungon loppu.
- Nisäkäsluokan ruumiin loppu.
- Luo luokka nimeltä Lehmä, joka perii nisäkkäiden luokan. Lehmä on johdettu luokka, kun taas Nisäkäs on perusluokka. { merkitsee tämän luokan alkua.
- Käytä julkisen käyttöoikeuden muokkaajaa merkitäksesi toiminnon, jonka olemme luomassa, julkisesti käytettäväksi. Se on käytettävissä tämän luokan ulkopuolelta.
- Ohita funktio eat(), joka määritettiin perusluokassa. { merkitsee funktion rungon alkua.
- Lause, joka tulostetaan konsolissa, kun tämä toiminto vedetään.
- Funktion eat() rungon loppu.
- Lehmän luokan rungon loppu.
- Kutsu main()-funktiota. { merkitsee tämän funktion rungon alkua.
- Luo Cow-luokan esiintymä ja anna sille nimi c.
- Kutsu Cow-luokassa määriteltyä eat()-funktiota.
- Ohjelman on palautettava arvo, kun se on suoritettu onnistuneesti.
- Main()-funktion loppu.
C++ Virtuaalinen toiminto
Virtuaalinen funktio on toinen tapa toteuttaa ajonaikaista polymorfismia C++. Se on erityinen funktio, joka on määritelty perusluokassa ja määritelty uudelleen johdetussa luokassa. Virtuaalifunktion ilmoittamiseen tulee käyttää virtuaalista avainsanaa. Avainsanan tulee edeltää funktion ilmoitusta perusluokassa.
Jos virtuaalinen funktioluokka periytyy, virtuaaliluokka määrittelee virtuaalifunktion uudelleen tarpeidensa mukaan. Esimerkiksi:
#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();
}
lähtö:
Tässä on kuvakaappaus koodista:
Koodin selitys:
- Sisällytä iostream-otsikkotiedosto koodiin käyttääksesi sen toimintoja.
- Sisällytä std-nimiavaruus koodiimme käyttääksesi sen luokkia kutsumatta sitä.
- Luo luokka nimeltä ClassA.
- Käytä julkisen käyttöoikeuden muokkaajaa merkitäksesi luokan jäsen julkisesti käytettäväksi.
- Luo virtuaalinen funktio nimeltä show(). Siitä tulee julkinen tilaisuus.
- Teksti, joka tulostetaan, kun show()-toimintoa kutsutaan. Loppu on a C++ avainsana, joka tarkoittaa loppuriviä. Se siirtää hiiren osoittimen seuraavalle riville.
- Virtuaalifunktion show() rungon loppu.
- Luokan A rungon loppu.
- Luodaan uusi luokka nimeltä ClassB, joka perii luokan ClassA. Luokasta A tulee perusluokka, kun taas luokasta B tulee johdettu luokka.
- Käytä julkisen käyttöoikeuden muokkaajaa merkitäksesi luokan jäsen julkisesti käytettäväksi.
- Määritä perusluokassa johdettu virtuaalifunktio show() uudelleen.
- Konsolille tulostettava teksti, kun vedetyssä luokassa määritetty show()-funktio kutsutaan.
- Show()-funktion rungon loppu.
- Johdetun luokan, ClassB, rungon loppu.
- Kutsu main()-funktiota. Ohjelmalogiikka tulisi lisätä sen runkoon.
- Luo osoitinmuuttuja nimeltä a. Se osoittaa luokkaan nimeltä ClassA.
- Luo esiintymä luokasta nimeltä ClassB. Esiintymälle annetaan nimi b.
- Määritä muuttujan a osoitteen b arvovarastot.
- Kutsua johdetussa luokassa määritetty show()-funktio. Myöhäinen sidonta on otettu käyttöön.
- Main()-funktion rungon loppu.
Käännösajan polymorfismi vs. Ajonaikainen polymorfismi
Tässä ovat tärkeimmät erot näiden kahden välillä:
| Kokoonpanoaikainen polymorfismi | Ajonaikainen polymorfismi |
|---|---|
| Sitä kutsutaan myös varhaiseksi sitoutumiseksi tai staattiseksi polymorfismiksi | Sitä kutsutaan myös myöhäiseksi/dynaamiseksi sitoutumiseksi tai dynaamiseksi polymorfismiksi |
| Menetelmää kutsutaan/kutsutaan käännösaikana | Menetelmää kutsutaan/kutsutaan ajon aikana |
| Toteutettu toimintojen ylikuormituksen ja käyttäjän ylikuormituksen kautta | Toteutettu menetelmän ohituksen ja virtuaalisten toimintojen kautta |
| Esimerkki, menetelmän ylikuormitus. Monilla menetelmillä voi olla samanlaiset nimet, mutta eri määrä tai tyyppisiä argumentteja | Esimerkki, menetelmän ohittaminen. Monilla menetelmillä voi olla samanlainen nimi ja sama prototyyppi. |
| Nopeampi suoritus, koska menetelmien etsintä tehdään käännösajan aikana | Hitaampi suoritus, koska menetelmän etsijä tehdään ajon aikana. |
| Less Joustavuutta ongelmanratkaisuun tarjotaan, koska kaikki on tiedossa käännösaikana. | Monimutkaisten ongelmien ratkaisemiseen tarjotaan paljon joustavuutta, koska menetelmät löydetään ajon aikana. |
Yhteenveto
- Polymorfismi tarkoittaa, että sillä on monia muotoja.
- Se tapahtuu, kun on olemassa periytymisen kautta liittyvien luokkien hierarkia.
- Polymorfismissa funktio voi käyttäytyä eri tavalla sen mukaan, mikä objekti kutsuu sitä.
- Käännösajan polymorfismissa kutsuttava funktio määritetään käännösajan aikana.
- Ajonaikaisessa polymorfismissa kutsuttava funktio määritetään ajon aikana.
- Käännösajan polymorfismi määritetään funktion ylikuormituksen ja operaattorin ylikuormituksen kautta.
- Funktioiden ylikuormituksessa on monia toimintoja, joilla on samanlaiset nimet, mutta erilaiset argumentit.
- Parametrit voivat vaihdella lukumäärän tai tyypin mukaan.
- Käyttäjän ylikuormituksessa sille määritellään uusi merkitys C++ operaattorit.
- Ajonaikainen polymorfismi saavutetaan funktion ohituksella.
- Funktioiden ohituksessa johdettu luokka antaa uuden määritelmän perusluokassa määritellylle funktiolle.







