Noudata käytäntöä, että kullekin luokalle luodaan oma header-tiedosto ja oma cpp-tiedosto, joilla on sama nimi kuin luokalla. Tämä hoituu automaattisesti, kun luot luokat Qt-Creatorin toiminnolla "Add New -> C++ Class". Tutustu aluksi UML-kaavion symbooleihin kts. https://peatutor.com/cplus/index.php#uml.
Animal
, joka sisältää virtuaalisen metodin callOut
. Tämä metodi tulostaa tekstin "Eläin ääntelee."Dog
, joka ylikirjoittaa metodin callOut
. Ylikirjoitetun metodin tulisi tulostaa teksti "Koira haukkuu!"main
-funktio, jossa luodaan Animal
-luokan olio ja Dog
-luokan olio.callOut
-metodia ja varmista, että oikea viesti tulostuu. C++-ohjelmoinnissa, kun sinulla on perintäsuhde luokkien Animal
ja Dog
välillä, voit luoda ja käsitellä olion joko kantaluokan (Animal
) tai perivänluokan (Dog
) osoittimen kautta. Molemmilla tavoilla on etunsa. Tarkastellaan ensin molempia tapoja:
Animal* dog = new Dog;
(Polymorfismi)Dog* dog = new Dog;
(Perivänluokan käyttö suoraan)Animal* dog = new Dog;
Tässä käytetään kantaluokan osoitinta, mutta luodaan perivänluokan olio. Tämä tarjoaa monia etuja:
Huom! Tässä tapauksessa Animal luokan destruktori on määritettävä virtuaaliseksi.
Voit käsitellä Dog
-oliota yleisemmällä Animal
-tyypillä. Tämä mahdollistaa koodin kirjoittamisen siten, että se voi käsitellä mitä tahansa Animal
-tyyppistä oliota (Dog
, Cat
, jne.), mikä lisää joustavuutta ja laajennettavuutta.
Animal* animals[] = { new Dog(), new Cat(), new Bird() };
for (int i = 0; i < 3; i++) {
animals[i]->callOut(); // Jokainen eläin toteuttaa oman luokkansa callOut-metodin
}
Funktiot voivat käsitellä Animal
-tyyppisiä olioita ilman, että niiden tarvitsee tietää perivää luokkaa:
void handleAnimal(Animal* animal) {
animal->callOut(); // Polymorfinen kutsu
}
Voit lisätä uusia eläinlajeja (Cat
, Bird
, jne.) ilman, että sinun tarvitsee muuttaa vanhaa koodia, joka käyttää kantaluokkaa (Animal
).
Dog* dog = new Dog;
Tässä käytetään perivänluokan osoitinta. Tämä voi olla hyödyllistä seuraavissa tilanteissa:
Jos haluat käyttää Dog
-luokan erityisiä metodeja tai jäsenmuuttujia, jotka eivät ole kantaluokassa, sinun täytyy käyttää Dog
-osoitinta:
Dog* dog = new Dog();
dog->getOwner(); // Ominaisuus, joka on vain Dog-luokassa, ei Animal-luokassa
Jos et tarvitse polymorfismia, suora Dog
-osoitin voi olla tehokkaampi, koska se ei aiheuta ylimääräistä suorituskykykustannusta virtuaalifunktiotaulun (vtable
) käytöstä (vtable on taulukko, joka sisältää osoittimet virtuaalisiin metodeihin).
Ominaisuus | Animal* dog = new Dog; |
Dog* dog = new Dog; |
---|---|---|
Polymorfismi | Kyllä | Ei |
Koodin joustavuus ja laajennettavuus | Kyllä | Ei |
Perivänluokan metodit käytettävissä | Ei ilman tyyppimuunnosta | Kyllä |
Suorituskyky | Hieman hitaampi (virtuaalitaulu) | Hieman nopeampi |
Animal*
ja milloin Dog*
?Animal*
, kun haluat hyödyntää polymorfismia ja käsitellä erilaisia eläinluokkia samalla tavalla.Dog*
, kun tiedät tarkalleen, että työskentelet vain Dog
-olioiden kanssa ja haluat käyttää sen erityisiä metodeja.
Animal* animal = new Dog(); // Animal-osoitin, mutta Dog-käytössä
animal->callOut(); // Kutsuu Dog:n toteuttamaa callOut-metodia
Dog* dog = new Dog();
dog->getOwner(); // Erityinen Dog-metodi