Wprowadzenie do programowania obiektowego
Programowanie obiektowe jest to specyficzna metodologia projektowania programów komupterowych charakteryzująca się następującymi właściwościami:
- abstrakcja
- hermetyzacja
- polimorfizm
- dziedziczenie
Abstrakcja to wyodrębnienie z rzeczywistości oraz uogólnienie (uproszczenie) najważniejszych cech problemu i wyrażeniu rozwiązania w obrębie tych cech. Np. Człowiek składa się wielu milardów komórek połączonych ze sobą, tworzących wiele autonomicznych organów współpracujących ze sobą. Natomiast w celu uproszczenia możemy najważniejsze cechy człowieka zapisać w taki sposób:
- rasa
- wzrost
- waga
- wiek
- imię
- nazwisko
- wykształcenie
Hermetyzacja polega na ukrywaniu pewnych danych składowych (cech obiektu) lub metod (funkcji składowych) obiektów danej klasy tak, aby były one dostępne tylko metodom składowym danej klasy lub funkcjom zaprzyjaźnionym.
Polimorfizm - wielopostaciowość. Mechanizmy pozwalające programiście używać wartości, zmiennych i podprogramów na kilka różnych sposobów. Inaczej mówiąc jest to możliwość wyabstrahowania wyrażeń od konkretnych typów[Wikipedia].
Dziedziczenie - to inaczej powtórne wykorzystanie cech oraz działań klasy podstawowej przez klasę pochodną oraz rozszerzenie klasy podstawowej o nowe metody.
Pytania sprawdzające
- Co to jest hermetyzacja?
- Co to jest polimorfizm?
- Co to jest dziedziczenie?
Klasa, obiekt, metoda
Klasa jest to zestaw cech oraz możliwych akcji na podstawie, której został zbudowany obiekt.
Obiekt jest reprezentantem klasy.
Klasa to inaczej własny typ danych zaprojektowy przez programistę umożliwiający dostęp do własności (cech) poprzez funkcje składowe klasy (metody).
Obiektem może być np. Bugatti 16.4 Veyron z 16 cylindrowym silnikiem widlastym (W16) z czterema turbosprężarkami, o pojemności skokowej 7993 cm3.
Bugatti Veyron jest reprezentantem klasy Samochod.
Obiekt to wycinek rzeczywistości posiadający własne cechy (właściwości) oraz mogący wykonywać pewne akcje (metody). Obiektem może wszystko w świecie rzeczywistym, np. samochody, ludzie, domy, komputery, itd.
Metoda - jest to funkcja składowa klasy, która ma dostęp do składowych, tworząc interfejs.
Przykład:
Zbudujemy klasę Samochód.
/* Program P1 - Klasa Samochod
* Wykonał Paweł Malinowski */
#include <iostream>
using namespace std;
class Samochod
{
public:
string marka;
string model;
int rocznik;
float pojemnosc;
float przyspieszenie; // przyspieszenie od 0 - 100 km/h
float spalanie; // cykl mieszany
void dodaj_samochod()
{
cout << "WPROWADZANIE NOWEGO SAMOCHODU" << endl;
cout << "Podaj marke samochodu: ";
cin >> marka;
cout << "Podaj model samochodu: ";
cin >> model;
cout << "Podaj rocznik samochodu: ";
cin >> rocznik;
cout << "Podaj pojemnosc silnika (cm3): ";
cin >> pojemnosc;
cout << "Podaj wartosc przyspieszenia od 0 do 100km/h (s): ";
cin >> przyspieszenie;
cout << "Podaj wartosc spalania w cyklu mieszanym (l): ";
cin >> spalanie;
}
void pokaz_samochod()
{
cout << endl << "Twoj samochod to: " << endl << endl;
cout << "Marka: " << marka << endl << "Model: " << model << endl;
cout << "Rocznik: " << rocznik << endl;
cout << "Pojemnosc: " << pojemnosc << " cm3" << endl;
cout << "Przyspieszenie: " << przyspieszenie << " s" << endl;
cout << "Spalanie: " << spalanie << " l";
}
};
int main()
{
Samochod s1;
s1.dodaj_samochod();
s1.pokaz_samochod();
return 0;
}
W wyniku wykonania się programu otrzymujemy:
WPROWADZANIE NOWEGO SAMOCHODU Podaj marke samochodu: Bugatti Podaj model samochodu: Veyron Podaj rocznik samochodu: 2018 Podaj pojemnosc silnika (cm3): 7993 Podaj wartosc przyspieszenia od 0 do 100km/h (s): 2.5 Podaj wartosc spalania w cyklu mieszanym (l): 24.1 Twoj samochod to: Marka: Bugatti Model: Veyron Rocznik: 2018 Pojemnosc: 7993 cm3 Przyspieszenie: 2.5 s Spalanie: 24.1 l Process returned 0 (0x0) execution time : 49.695 s Press any key to continue.
Specyfikatory dostępu: public, private i protected
- Specyfikator public - oznacza dostęp publiczny do wszystkich składowych klasy
- Specyfikator private - oznacza, że tylko metody tej klasy mają dostęp do składowych klasy
- Specyfikator protected - oznacza, że składowa klasy czy metoda będą dostępne (tak jakby były publiczne) w klasach pochodnych danej klasy, a zachowują się jak prywatne dla wszystkich innych klas i funkcji.
Składowe mają takie prawa dostępu jak poprzedzający je specyfikator dostępu. Jeżeli nie określono żadnego specyfikatora, domyślnie jest specyfikator private
Przykład:
Program będzie się składał z trzech plików: pliku głównego, pliku nagłówkowego oraz pliku z ciałem metod składowych klasy. Program będzie wczytywał z pliku Ryby.txt dane dotyczące gatunku, wymiaru ochronnego, okresu ochronnego oraz ile sztuk ryb można złowić w ciągu doby.
Plik Ryba.h - plik nagłówkowy ("spis treści" klasy)
/* Program - Na ryby - plik Ryba.h
* Wykonał Paweł Malinowski */
#include <iostream>
using std::string;
class Ryba
{
public:
string gatunek;
string wymiar;
string okres;
string ile_sztuk;
int ktora_ryba;
void wczytaj_rybe();
void pokaz_rybe();
};
Plik Ryba.cpp - ciało klasy czyli definicja wszystkich metod składowych klasy
/* Program - Na ryby - plik Ryba.cpp
* Wykonał Paweł Malinowski */
#include <iostream>
#include "Ryba.h"
#include <fstream>
using std::fstream;
using std::ios;
using std::cout;
using std::endl;
void Ryba::wczytaj_rybe()
{
fstream fout;
fout.open("/Users/pawelmalinowski/Documents/C++/Ryby/Ryby.txt", ios::in);
if (fout.good() == true)
{
int nr_linii = (ktora_ryba - 1) * 4 + 1;
string linia;
int licznik = 1;
while(getline(fout, linia))
{
if (licznik == nr_linii) gatunek = linia;
if (licznik == nr_linii + 1) wymiar = linia;
if (licznik == nr_linii + 2) okres = linia;
if (licznik == nr_linii + 3) ile_sztuk = linia;
licznik++;
}
fout.close();
}
else
{
cout << "Plik nie istnieje!";
exit(0);
}
}
void Ryba::pokaz_rybe()
{
cout << "================================================" << endl;
cout << gatunek << endl;
cout << "Wymiar ochronny: " << wymiar << endl;
cout << "Okres ochronny: " << okres << endl;
cout << "Ile sztuk na dobe: " << ile_sztuk << endl;
cout << "================================================" << endl;
}
Plik main.cpp
/* Program - Na ryby - plik main.cpp
* Wykonał Paweł Malinowski */
#include <iostream>
#include "Ryba.h"
int main()
{
Ryba r[10];
for (int i = 0; i < 10; i++)
{
r[i].ktora_ryba = i + 1;
r[i].wczytaj_rybe();
r[i].pokaz_rybe();
}
return 0;
}
Wynik działania programu:
================================================ Boleń Wymiar ochronny: 40 cm Okres ochronny: 1 stycznia - 30 kwietnia Ile sztuk na dobe: 2 szt. ================================================ ================================================ Brzana Wymiar ochronny: 40 cm Okres ochronny: 1 stycznia - 30 czerwca Ile sztuk na dobe: 3 szt. ================================================ ================================================ Głowacica Wymiar ochronny: 70 cm Okres ochronny: 1 marca - 31 maja Ile sztuk na dobe: 1 szt. ================================================ ================================================ Sandacz Wymiar ochronny: 50 cm Okres ochronny: 1 stycznia - 31 maja Ile sztuk na dobe: 2 szt. ================================================ ================================================ Sieja Wymiar ochronny: 35 cm Okres ochronny: 1 października - 31 grudnia Ile sztuk na dobe: 2 szt. ================================================ ================================================ Sielawa Wymiar ochronny: 18 cm Okres ochronny: 1 października - 31 grudnia Ile sztuk na dobe: - ================================================ ================================================ Sum Wymiar ochronny: 70 cm Okres ochronny: 1 stycznia - 31 maja Ile sztuk na dobe: 1 szt. ================================================ ================================================ Szczupak Wymiar ochronny: 50 cm Okres ochronny: 1 stycznia - 30 kwietnia Ile sztuk na dobe: 2 szt. ================================================ ================================================ Świnka Wymiar ochronny: 25 cm Okres ochronny: 1 stycznia - 15 maja Ile sztuk na dobe: - ================================================ ================================================ Węgorz Wymiar ochronny: 60 cm Okres ochronny: 1 grudnia - 31 marca Ile sztuk na dobe: 2 szt. ================================================Pytania sprawdzające
- Co to jest klasa?
- Co to jest obiekt?
- Co to jest metoda?
- Co to są specyfikatory dostępu? Wyjaśnij każdy z nich.
-
Napisz program, który wykorzystuje klasę Książka. Jako składowe klasy podaj:
- autora,
- tytuł,
- wydawnictwo,
- rok wydania
-
Napisz program z wykorzystaniem klasy Student. Jako składowe klasy podaj:
- imię,
- nazwisko,
- pesel,
- uczelnia,
- wydział,
- rok studiów,
Hermetyzacja, konstruktor, destruktor
Hermetyzacja to inaczej ograniczenie dostępu do atrybutów klasy lub metod w celu ochrony tych danych przed przypadkową zmianą. Dostęp do prywatnych atrybutów lub metod mogą mieć metody z klauzulą public lub funkcje zaprzyjaźnione.
Tyle teorii. Teraz przejdźmy do przykładu. Poniżej plik Bateria.h
/* Program - Baterie - hermetyzacja
* Wykonał Paweł Malinowski */
#include <iostream>
using namespace std;
class Bateria
{
string rodzaj_ogniw;
float napiecie;
float pojemnosc;
float prad_rozladowania;
int ilosc_cykli;
public:
Bateria(string = "Nano-fosfatowe (LiFePO4)", float = 3.3, float = 2500, float = 50, int = 1000);
~Bateria();
void pokaz();
};
Wszystkie atrybuty są prywatne, natomiast metody są publiczne.
Poniżej plik Bateria.cpp
/* Program - Baterie - hermetyzacja
* Wykonał Paweł Malinowski */
#include <iostream>
#include "Bateria.h"
using namespace std;
Bateria::Bateria(string ro, float n, float p, float pr, int ic)
{
rodzaj_ogniw = ro;
napiecie = n;
pojemnosc = p;
prad_rozladowania = pr;
ilosc_cykli = ic;
}
Bateria::~Bateria()
{
}
void Bateria::pokaz()
{
cout << "Rodzaj baterii: " << rodzaj_ogniw << endl;
cout << "Napiecie: " << napiecie << " V" << endl;
cout << "Pojemnosc: " << pojemnosc << " mAh" << endl;
cout << "Prad rozladowania: " << prad_rozladowania << " A" << endl;
cout << "Ilosc cykli: " << ilosc_cykli << endl;
cout << "============================================" << endl;
}
Poniżej plik main.cpp
/* Program - Baterie - hermetyzacja
* Wykonał Paweł Malinowski */
#include <iostream>
#include "Bateria.h"
using namespace std;
int main()
{
Bateria b1;
b1.pokaz();
Bateria b2("Litowo-jonowe",3.6,2500,20,1000);
b2.pokaz();
Bateria b3("Alkaliczna",3.0);
b3.pokaz();
return 0;
}
Konstruktor - metoda składowa klasy, której nazwa jest identyczna co nazwa klasy. Podczas tworzenia obiektu jest wywoływany konstruktor, którego zadaniem jest prawidłowe przypisanie wartości początkowych do obiektu. Dzięki temu unikniemy sytuacji, gdy obiekt nie będzie posiadał przypisanych wartości początkowych. Podczas tworzenia metody konstruktora nie podajemy jaką wartość zwraca. W klasie może posiadać więcej konstruktorów. W takiej sytuacji mamy do czynienia z przeciążeniem nazwy konstruktora. Dzięki wykorzystaniu konstruktora nie musimy się martwić o niespójność danych, gdyż w momencie tworzenia obiektu otrzymuje on wartości początkowe.
Destruktor - jest to metoda składowa klasy uruchamiana po usunięciu obiektu klasy. Jej nazwa jest identyczna jak nazwa klasy, ale poprzedzona znakiem "~". Na przykład Bateria::~Bateria. Jest to nazwa destruktora poprzedzona nazwą klasy rozdzielona operatorem zasięgu (::). Destruktor służy do "czyszczenia" po obiekcie. Podczas tworzenia destruktora nie zwraca on żadnego typu. Destruktor w przeciwieństwie do konstruktora może być tylko jeden. Nie można przeciążać nazwy destruktora. Dodatkowo do destruktora nie przekazujemy żadnych argumentów.
Zarówno konstruktor jak i destruktor nie są wymagane w programie. Jednakże jeśli ich jawnie nie podamy, to zostaną one automatycznie wygenerowane. Natomiast nic nie będą robić.
#include <iostream>
using namespace std;
class Lampa
{
public:
string rodzaj;
int jasnosc;
Lampa(string r, int j)
{
rodzaj = r;
jasnosc = j;
}
Lampa(string r)
{
rodzaj = r;
jasnosc = 1000;
}
~Lampa()
{
jasnosc = 0;
}
void pokaz()
{
cout << "+++++++++++++++++++++++++++++" << endl;
cout << "Rodzaj lampy: " << rodzaj << endl;
cout << "Jasnosc: " << jasnosc << endl;
}
};
int main()
{
Lampa l1("LED", 2000);
Lampa *wskob = &l1;
l1.pokaz();
int Lampa::*wskint;
wskint = &Lampa::jasnosc;
cout << "Wartosc wskaznika jasnosc: " << l1.*wskint << endl;
l1.~Lampa();
cout << "Wartosc wskaznika po wywolaniu destruktora: " << l1.*wskint << endl;
wskint = NULL;
cout << "Wskaznik zostal wyzerowany: " << l1.*wskint << endl;
Lampa *l2 = new Lampa("HALOGEN");
l2->pokaz();
cout << "Wartosc skladowej jasnosc poprzez wskaznik: " << l2->jasnosc << endl;
l2->jasnosc = NULL;
cout << "Wartosc skladowej jasnosc wyzerowanego wskaznika: " << l2->jasnosc << endl;
delete l2;
cout << "Wartosc skladowej jasnosc nieistniejacego obiektu: " << l2->jasnosc << endl;
//l2->pokaz();
return 0;
}
+++++++++++++++++++++++++++++ Rodzaj lampy: LED Jasnosc: 2000 Wartosc wskaznika jasnosc: 2000 Wartosc wskaznika po wywolaniu destruktora: 0 Wskaznik zostal wyzerowany: 1862174720 +++++++++++++++++++++++++++++ Rodzaj lampy: HALOGEN Jasnosc: 1000 Wartosc skladowej jasnosc poprzez wskaznik: 1000 Wartosc skladowej jasnosc wyzerowanego wskaznika: 0 Wartosc skladowej jasnosc nieistniejacego obiektu: 0 Process returned 0 (0x0) execution time : 0.117 s Press any key to continue.
Pytania sprawdzające
- Co to jest hermetyzacja?
- Co to jest konstruktor? Jak się tworzy konstruktor.
- Co to jest destruktor? Jak się tworzy destruktor.
-
Napisz program z wykorzystaniem klasy Dom. Jako składowe klasy podaj:
- powierzchnia domu,
- ilość pokoi,
- rok budowy,
- lokalizacja
- powierzchnia ogrodu
Funkcje zaprzyjaźnione
Funkcje zaprzyjaźnione - jest to funkcja, która ma dostęp do wszystkich składowych klasy, pomimo iż są one prywatne. Deklarację przyjaźni wykonujemy w klasie.
/* Program - Baterie - hermetyzacja
* Wykonał Paweł Malinowski */
#include <iostream>
using namespace std;
class Bateria
{
string rodzaj_ogniw;
float napiecie;
float pojemnosc;
float prad_rozladowania;
int ilosc_cykli;
public:
Bateria(string = "Nano-fosfatowe (LiFePO4)", float = 3.3, float = 2500, float = 50, int = 1000);
~Bateria();
void pokaz();
friend void sprawdz(Bateria b, float nap);
};
Wszystkie atrybuty są prywatne, natomiast metody są publiczne.
Poniżej plik Bateria.cpp
/* Program - Baterie - hermetyzacja
* Wykonał Paweł Malinowski */
#include <iostream>
#include "Bateria.h"
using namespace std;
Bateria::Bateria(string ro, float n, float p, float pr, int ic)
{
rodzaj_ogniw = ro;
napiecie = n;
pojemnosc = p;
prad_rozladowania = pr;
ilosc_cykli = ic;
}
Bateria::~Bateria()
{
}
void Bateria::pokaz()
{
cout << "Rodzaj baterii: " << rodzaj_ogniw << endl;
cout << "Napiecie: " << napiecie << " V" << endl;
cout << "Pojemnosc: " << pojemnosc << " mAh" << endl;
cout << "Prad rozladowania: " << prad_rozladowania << " A" << endl;
cout << "Ilosc cykli: " << ilosc_cykli << endl;
cout << "============================================" << endl;
}
Poniżej plik main.cpp
/* Program - Baterie - hermetyzacja
* Wykonał Paweł Malinowski */
#include <iostream>
#include "Bateria.h"
using namespace std;
void sprawdz(Bateria b, float nap)
{
if (b.napiecie >= nap)
cout << "Bateria " << b.rodzaj_ogniw << " posiada napiecie wieksze lub rowne " << nap << "V";
}
int main()
{
Bateria b1;
b1.pokaz();
Bateria b2("Litowo-jonowe",3.6,2500,20,1000);
b2.pokaz();
Bateria b3("Alkaliczna",3.0);
b3.pokaz();
sprawdz(b2,2.5);
return 0;
}
Rodzaj baterii: Nano-fosfatowe (LiFePO4) Napiecie: 3.3 V Pojemnosc: 2500 mAh Prad rozladowania: 50 A Ilosc cykli: 1000 ============================================ Rodzaj baterii: Litowo-jonowe Napiecie: 3.6 V Pojemnosc: 2500 mAh Prad rozladowania: 20 A Ilosc cykli: 1000 ============================================ Rodzaj baterii: Alkaliczna Napiecie: 3 V Pojemnosc: 2500 mAh Prad rozladowania: 50 A Ilosc cykli: 1000 ============================================ Bateria Litowo-jonowe posiada napiecie wieksze lub rowne 2.5V Process returned 0 (0x0) execution time : 0.028 s Press any key to continue.Pytania sprawdzające
- Co to jest funkcja zaprzyjaźniona?
- Kto decyduje o przyjaźni?
-
Napisz program wykorzystujący klasę Samochód. Jako składowe klasy podaj:
- marka,
- model,
- pojemnosc,
- spalanie,
- dostępna ilość paliwa
Dziedziczenie
Dziedziczenie - Przekazywanie swoich cech potomkom. W programowaniu chodzi o przekazywanie atrybutów klasom pochodnym. Klasa podstawowa jest to klasa po której się dziedziczy. Klasa pochodna jest to nowa klasa, która dziedziczy z klasy podstawowej (bazowej).
Dziedziczenie wielokrotne - oznacza, że klasa pochodna staje się klasą podstawową dla innej klasy pochodnej.
Przy dziedziczeniu stosujemy specyfikatory dostępu podobnie jak robiliśmy to przy definicji klasy. Mamy trzy specyfikatory dostępu przy dziedziczeniu:
- public - dziedziczenie publiczne - wszystkie składowe klasy podstawowej ze specyfikatorem public i protected w klasie pochodnej pozostają bez zmian
- protected - dziedziczenie chronione - wszystkie składowe klasy podstawowej ze specyfikatorem public i protected w klasie pochodnej stają się protected. Jest jeden wyjątek. Funkcje zaprzyjaźnione również mają dostęp do składników klasy podstawowej.
- private - dziedziczenie prywatne - wszystkie składowe klasy podstawowej ze specyfikatorem public i protected w klasie pochodnej stają się private
Dziedziczenie dotyczy tylko składowych klasy oraz metod. Z klasy podstawowej nie zostaną odziedziczone konstruktory oraz destruktory.
/* Program - Samochody - dziedziczenie
* Wykonał Paweł Malinowski */
#include <iostream>
using namespace std;
class Samochod
{
string rodzaj;
string marka;
string model;
int rocznik;
float moc;
float przyspieszenie;
public:
Samochod(string rodz, string mar, string mod, int rocz, float m, float przysp)
{
rodzaj = rodz;
marka = mar;
model = mod;
rocznik = rocz;
moc = m;
przyspieszenie = przysp;
}
void pokaz()
{
cout << endl << "Twoj samochod " << rodzaj << " to: " << endl << endl;
cout << "Marka: " << marka << endl << "Model: " << model << endl;
cout << "Rocznik: " << rocznik << endl;
cout << "Moc: " << moc << " kW" << endl;
cout << "Przyspieszenie: " << przyspieszenie << " s" << endl;
}
};
class Hybrydowy :public Samochod
{
public:
void pokaz()
{
Samochod::pokaz();
}
Hybrydowy(string rodz, string mar, string mod, int rocz, float m, float przysp)
:Samochod(rodz, mar, mod, rocz, m, przysp)
{
}
};
class Elektryczny :public Hybrydowy
{
int zasieg;
public:
void pokaz()
{
Samochod::pokaz();
cout << "Zasieg: " << zasieg << endl;
}
Elektryczny(string rodz, string mar, string mod, int rocz, float m, float przysp, int zas)
:Hybrydowy(rodz, mar, mod, rocz, m, przysp)
{
zasieg = zas;
}
};
int main()
{
Samochod s1("spalinowy", "Honda", "Civic X Type R GT", 2020, 235.0, 5.8);
s1.pokaz();
Hybrydowy h1("hybrydowy", "BMW", "i8", 2020, 266.25, 4.2);
h1.pokaz();
Elektryczny e1("elektryczny", "Tesla", "X AWD", 2020, 450.0, 2.9, 487);
e1.pokaz();
return 0;
}
Wynik działania programu.
Twoj samochod spalinowy to: Marka: Honda Model: Civic X Type R GT Rocznik: 2020 Moc: 235 kW Przyspieszenie: 5.8 s Twoj samochod hybrydowy to: Marka: BMW Model: i8 Rocznik: 2020 Moc: 266.25 kW Przyspieszenie: 4.2 s Twoj samochod elektryczny to: Marka: Tesla Model: X AWD Rocznik: 2020 Moc: 450 kW Przyspieszenie: 2.9 s Zasieg: 487 Process returned 0 (0x0) execution time : 0.028 s Press any key to continue.Pytania sprawdzające
- Co to jest dziedziczenie?
- Co to jest klasa podstawowa?
- Co to jest klasa pochodna?
- Co oznacza dziedziczenie wielokrotne?
- Omów specyfikatory dostępu dla dziedziczenia. Jak zachowują się składowe klasy pochodnej dla różnych specyfikatorów?
-
Napisz program z wykorzystaniem klas Osoba, Student. Klasa Student dziedziczy publicznie po klasie Osoba. W klasie osoba podaj następujące składowe klasy:
- imię,
- nazwisko,
- pesel
- uczelnia,
- wydział,
- rok studiów
-
Napisz program z wykorzystaniem klas Osoba, Sportowiec, Koszykarz. Wykorzystaj dziedziczenie wielokrotne. Sportowiec dziedziczy publicznie z klasy Osoba, a Koszykarz dziedziczy publicznie z klasy Sportowiec.
Jako składowe klasy Osoba podaj:
- imię,
- nazwisko,
- pesel
- test Coopera,
- bieg na 100 metrów
- skok dosiężny,
- pozycja,
- skuteczność z lini rzutów osobistych (%)
Polimorfizm, funkcje wirtualne
Polimorfizm - wielopostaciowość. W praktyce wiąże się to z wykorzystaniem polimorficznego wskaźnika do abstrakcyjnej klasy podstawowej, który wskazuje na obiekty pochodzące z klas pochodnych. Specjalna metoda podstawowej klasy abstrakcyjnej tzw. czysta funkcja jest przeciążana przez metody klas pochodnych.
Funkcja wirtualna (virtual) - specjalna tzw. czysta metoda abstrakcyjnej klasy podstawowej, która jest przeciążana przez metody klas pochodnych.
/* Program - Samochody - dziedziczenie
* Wykonał Paweł Malinowski */
#include <iostream>
#include <math.h>
using namespace std;
class Bryla
{
public:
virtual void objetosc()=0;
};
class Kula :public Bryla
{
float r;
public:
Kula(float x)
{
r = x;
}
virtual void objetosc()
{
cout << "KULA" << endl;
cout << "Objetosc kuli o promieniu " << r << " cm wynosi " << 4 * M_PI * pow(r, 3) / 3 << " cm3" << endl << endl;
}
};
class Torus :public Bryla
{
float r;
float R;
public:
Torus(float x, float y)
{
r = x;
R = y;
}
virtual void objetosc()
{
cout << "TORUS" << endl;
cout << "Objetosc torusa o promieniu okregu " << r << " cm oddalony od srodka o " << R << " cm wynosi " << 2 * pow(M_PI, 2) * R * pow(r, 2) << " cm3" << endl << endl;
}
};
class Tetraedr :public Bryla
{
float a;
public:
Tetraedr(float x)
{
a = x;
}
virtual void objetosc()
{
cout << "TETRAEDR" << endl;
cout << "Objetosc tetraedru o boku " << a << " cm wynosi " << (pow(2, 1/2) * pow(a, 3)) / 12 << " cm3" << endl << endl;
}
};
class Oktaedr :public Bryla
{
float a;
public:
Oktaedr(float x)
{
a = x;
}
virtual void objetosc()
{
cout << "OKTAEDR" << endl;
cout << "Objetosc oktaedru o boku " << a << " cm wynosi " << (pow(2, 1/2) * pow(a, 3)) / 3 << " cm3" << endl << endl;
}
};
int main()
{
Kula k(5);
Torus t(3, 5);
Tetraedr te(10);
Oktaedr o(10);
Bryla *bryla;
bryla = &k;
bryla -> objetosc();
bryla = &t;
bryla -> objetosc();
bryla = &te;
bryla -> objetosc();
bryla = &o;
bryla -> objetosc();
return 0;
}
Wynik działania programu
KULA Objetosc kuli o promieniu 5 cm wynosi 523.599 cm3 TORUS Objetosc torusa o promieniu okregu 3 cm oddalony od srodka o 5 cm wynosi 888.264 cm3 TETRAEDR Objetosc tetraedru o boku 10 cm wynosi 83.3333 cm3 OKTAEDR Objetosc oktaedru o boku 10 cm wynosi 333.333 cm3 Process returned 0 (0x0) execution time : 0.026 s Press any key to continue.Pytania sprawdzające
- Co to jest polimorfizm?
- Co to jest funkcja wirtualna? Do czego służy?
- Co oznacza przeciążenie nazwy funkcji?
- Napisz program z wykorzystaniem klasy figura. Umieść w niej 3 czyste funkcje wirtualne do obliczania: obwodu, pola powierzchni, sumy kątów oraz promienia okręgu wpisanego w daną figurę dla następujących figur geometrycznych - (trójkąt równoboczny, kwadrat, pięciokąt foremny, sześciokąt foremny). Napisz klasy dla wyżej wymienionych figur wraz z funkcjami wirtualnymi, które wykonują obliczenia dla obwodu, pola powierzchni, sumy kątów oraz promienia okręgu wpisanego dla konkretnej figury.