Celem tego kursu/wykładu jest nauka programowania obiektowego w języku C++. Zostaną podjęte ważne tematy związane z paradygmatem programowania obiektowego OOP - Object Oriented Programming.

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.


  1. Co to jest hermetyzacja?
  2. Co to jest polimorfizm?
  3. 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/* 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)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* 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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 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.
    ================================================
  1. Co to jest klasa?
  2. Co to jest obiekt?
  3. Co to jest metoda?
  4. Co to są specyfikatory dostępu? Wyjaśnij każdy z nich.
  1. Napisz program, który wykorzystuje klasę Książka. Jako składowe klasy podaj:
    • autora,
    • tytuł,
    • wydawnictwo,
    • rok wydania
    Napisz metody do pobierania oraz do wyświetlania tych informacji na ekranie.
  2. Napisz program z wykorzystaniem klasy Student. Jako składowe klasy podaj:
    • imię,
    • nazwisko,
    • pesel,
    • uczelnia,
    • wydział,
    • rok studiów,
    Napisz metody do pobierania danych oraz do wyświetlania ich na ekranie.

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 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ć.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#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.

  1. Co to jest hermetyzacja?
  2. Co to jest konstruktor? Jak się tworzy konstruktor.
  3. Co to jest destruktor? Jak się tworzy destruktor.
  1. Napisz program z wykorzystaniem klasy Dom. Jako składowe klasy podaj:
    • powierzchnia domu,
    • ilość pokoi,
    • rok budowy,
    • lokalizacja
    • powierzchnia ogrodu
    Wykorzystaj konstruktor do zainicjalizowania obiektu danymi. Nie podawaj danych domyślnych.

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.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* 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.
  1. Co to jest funkcja zaprzyjaźniona?
  2. Kto decyduje o przyjaźni?
  1. Napisz program wykorzystujący klasę Samochód. Jako składowe klasy podaj:
    • marka,
    • model,
    • pojemnosc,
    • spalanie,
    • dostępna ilość paliwa
    Utwórz trzy obiekty klasy Samochód. Utwórz funkcję zaprzyjaźnioną do której przekażesz obiekt klasy Samochód oraz odległość w kilometrach. Funkcja sprawdza czy dany obiekt ma wystarczającą ilość paliwa by przejechać podaną odległość.

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.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* 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.
  1. Co to jest dziedziczenie?
  2. Co to jest klasa podstawowa?
  3. Co to jest klasa pochodna?
  4. Co oznacza dziedziczenie wielokrotne?
  5. Omów specyfikatory dostępu dla dziedziczenia. Jak zachowują się składowe klasy pochodnej dla różnych specyfikatorów?
  1. 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
    Rozszerz klasę Student o następujące składowe klasy:
    • uczelnia,
    • wydział,
    • rok studiów
  2. 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
    Jako składowe klasy Sportowiec podaj:
    • test Coopera,
    • bieg na 100 metrów
    Jako składowe klasy Koszykarz podaj:
    • 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.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
83
/* 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.
  1. Co to jest polimorfizm?
  2. Co to jest funkcja wirtualna? Do czego służy?
  3. Co oznacza przeciążenie nazwy funkcji?
  1. 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.