Programowanie obiektowe
Specjalność: Automatyka
Semestr VII – Wykład
Zaliczenie poprzez obecność na wykładach, lub pozytywne rozwiązanie
testu końcowego
Semestr VIII -
Laboratorium
Ćwiczenia laboratoryjne na programie Borland Builder C++ 6.0
Wykład: dr inż. Aleksander Nawrat, pok. 935a
Bruce Eckel, „Thinking in C++”, Helion, 2000.
Grady Booch, „Object Oriented Design with Applications”, B.
Cummings, 1993.
Jesse Liberty, „C++ -- Księga eksperta”, Helion, 2000.
Bertrand Meyer, „Object-oriented software construction”, Prentice
Hall, 1988.
B. Stroustrup, „The C++ Programming Language”, Addison-Wesley,
Reading, Mass., 1991.
Andrzej Stasiewicz, „C++ całkiem inny świat”, Helion 2000.
Literatura
Program
wykładu:
4. Klasy
5. Zaawansowane sterowanie programem.
6. Zarządzanie pamięcią. Zaawansowane wykorzystanie wskaźników.
7. Referencje. Zaawansowane referencje i wskaźniki.
8. Zaawansowane funkcje. Przeciążanie operatorów. Tablice.
9. Dziedziczenie i polimorfizm.
10. Zaawansowany polimorfizm. Listy.
11. Specjalne klasy i funkcje. Preprocesor.
12. Obiektowo zorientowana analiza i projektowanie. Szablony.
Wyjątki i obsługa błędów.
1. Wstęp do C++. Program w C++.
2. Zmienne i stałe. Instrukcje i wyrażenia.
3. Funkcje.
13. Programowanie wizualne w C++. Sposób konstruowania aplikacji
wizualnych w zależności od kompilatora C++.
14. C++ a programowanie zdarzeniowe. Funkcje API Windows i ich
zastosowania.
15. Komponenty VCL. Grafika – własności Canvas. Aplikacja może
mieć wiele okien.
Wstęp do C++
Dlaczego C++ to właściwy wybór?
C++ jest językiem profesjonalnych programistów,
pozwala na szybkie tworzenie aplikacji w bardzo bogatym i łatwo
dostępnym środowisku,
aktualnie dostępne narzędzia, oferowane przez C++, powodują że
pisanie dużych, komercyjnych aplikacji jest bardzo proste.
Rys historyczny –
C++ to stosunkowo nowy język
Na samym początku programiści mieli do dyspozycji bardzo proste zestawy instrukcji –
język maszynowy. Instrukcje te były reprezentowane przez ciągi zer i jedynek.
Po wynalezieniu asemblerów, programy zaczęto zapisywać za pomocą mnemoników
instrukcji maszynowych takich jak MOV czy ADD. Stały się one bardziej czytelne i
łatwiejsze do pisania.
Z czasem zaczęły powstawać języki wyższego poziomu takie jak np. BASIC, PASCAL czy
C. Języki te pozwalały pisać programy bardziej zbliżone do zwykłego języka np.: let
i=100. Takie instrukcje były tłumaczone przez kompilatory i interpretery na instrukcje
języka maszynowego.
Interpretery takie jak BASIC, wykonywały program na bieżąco.
Nowe kompilatory tłumaczą tekst programu na tzw. kod obiektowy. Ten pierwszy krok to
kompilacja. Kompilator tworzy plik (.OBJ). Drugi krok to łączenie czyli konsolidacja
(linking). Linker tłumaczy plik obiektowy na program wykonywalny, możliwy do
uruchomienia w systemie operacyjnym
Interpretery, ze względu na wykonywanie programu na bieżąco,
stanowią wygodne i łatwe w obsłudze narzędzie programisty.
Cele programistów obecnie (w dobie gdy komputery stają się
coraz mniejsze, tańsze i szybsze, ceny pamięci spadły)
Kompilatory wprowadzają dodatkowe elementy: kompilację i łączenie,
które są stosunkowo niewygodne. Jednak z drugiej strony, program
stworzony przez kompilator jest zdecydowanie szybszy niż program
wykonywany przez interpreter.
Cele programistów dawniej:
tworzenie krótkich kawałków kodu, które można było szybko
uruchomić,
programy musiały być małe, ponieważ pamięć była droga,
musiały być szybkie, ponieważ czas procesora również był drogi.
Interpretery i komplilatory.
„Obecnie najdroższy jest czas programisty”
Dobrze napisany, elastyczny kod jest w cenie. Elastyczny, to znaczy
podatny na modyfikacje wyznaczone przez zmiany wymagań, łatwy
do rozbudowy.
Programowanie proceduralne, strukturalne i
obiektowe.
Programowanie proceduralne polega na wykonywaniu szeregu
czynności na zbiorze danych.
Programowanie strukturalne pozwala na usystematyzowanie
dostępu do procedur i umożliwia operowanie na dużych zbiorach
danych.
Główna idea stojąca za programowaniem strukturalnym jest tak
prosta jak zasada „dziel i zwyciężaj”.
Każde zadanie, które jest zbyt duże aby je łatwo opisać, jest
rozbijane na szereg mniejszych „podzadań” tak długo, aż wszystkie
„podzadania” staną się możliwe do opisania i zrozumienia.
Zalety i wady programowania strukturalnego:
+
pozwala na skuteczne rozwiązywanie dużych problemów
-
oddzielenie danych od programów, które na nich operują.
Powoduje to,
że całe zadanie staje się coraz mniej zrozumiałe i trudniejsze do
opanowania wraz ze wzrostem ilości danych.
-
Im więcej operacji chce się wykonać na danych, tym większy się
tworzy
bałagan.
Programowanie obiektowe
Esencją programowania obiektowego jest połączenie danych i
procedur, które na nich operują w jedną całość – „obiekt” –
samodzielną jednostkę z własną „tożsamością” i charakterystyką.
Programiści wykorzystujący styl proceduralny stale szukają nowych
rozwiązań dla starych problemów.
Inny model postępowania to :
Tworzenie takich składników o znanych właściwościach, które łatwo
jest adaptować do własnych potrzeb i wykorzystywać we własnych
programach. Odbywa się to w oddzieleniu od sprzętu
Przykład:
Gdy
elektronik
potrzebuje
do
swojego
zaprojektowanego układu tranzystora, to czy robi on nowy
tranzystor, czy idzie do magazynu, w którym wyszukuje potrzebny
mu element. Podobne możliwości dało specjalistom od
oprogramowania programowanie obiektowe.
C++ w pełni pozwala na obiektowe programowanie z wykorzystaniem
czterech „filarów” tego stylu programowania.
Hermetyzacj
a
Ukrycie danych
Dziedziczeni
e
Polimorfiz
m
C++ i programowanie obiektowe
Filary programowania
obiektowego
Hermetyzacja
Przykładowo: tworząc nowy układ elektroniczny, łączymy zazwyczaj
różne elementy elektroniczne. Mogą to być przykładowo rezystory,
kondensatory czy tranzystory. Każda z części elektronicznych takich
jak przykładowo tranzystor posiada odrębne właściwości i
zachowanie. Konstruktor może z niego korzystać bez dokładnego
zrozumienia zasad fizycznych jego działania – wystarczy, że będzie
widział, co on robi.
Żeby to osiągnąć, tranzystor musi stanowić zamkniętą całość i
całkowicie wykonywać postawione mu zadanie. Wykonywanie
jednej, konkretnej czynności nosi nazwę hermetyzacji.
Wszystkie cechy tranzystora są „zamknięte” (hermetyzowane) w
obiekcie „tranzystor”; nie są rozprowadzane po obwodzie. Nie trzeba
dokładnie wiedzieć, jak działa tranzystor, aby go efektywnie
wykorzystać.
C++ pozwala na tworzenie hermetyzacji i ukrywanie danych poprzez
możliwość tworzenia typów zwanych klasami.
Ukrycie danych
Raz stworzona, dobrze zdefiniowana klasa stanowi w pełni
hermetyczną jednostkę; używana jest jako całość.
Wewnętrzne działanie klasy powinno być dla użytkownika
niewidoczne; użytkownik dobrze zdefiniowanej klasy nie musi
wiedzieć, jak ona działa, musi jedynie wiedzieć, jak ją
wykorzystać do własnych potrzeb.
Dziedziczenie i wielokrotne używanie
W latach 80’ jedna z firm postanowiła stworzyć nowy rodzaj telefonu
do domowego użytku. Pomysłodawcy nie chcieli zaczynać od zera,
chcieli szybko wejść na rynek. Wzięli zwykły telefon i rozbudowali go.
Nowy telefon był zwykłym starym telefonem rozszerzonym o nowe
możliwości.
Możliwe
było
wykorzystanie
wszystkich
funkcji
dostępnych dla zwykłego telefonu oraz dodano pewne nowe funkcje.
C++ pozwala na wykorzystanie zasady wielokrotnego użycia
poprzez dziedziczenie.
Nowy typ może być stworzony jako rozszerzenie typu już istniejącego.
Nowa klasa jest wyprowadzana z istniejącego typu, tak jak w
przykładzie – nowy telefon był wyprowadzany ze starego, odziedziczył
wszystkie jego możliwości i został wzbogacony o nowe funkcje.
Rozszerzony telefon zachowywał się nieco odmiennie. Zamiast
dzwonka włączał się ekran, a głos mówił „Telefon do Ciebie”. Centrala
nie wiedziała o nowych funkcjach tego telefonu jedynie tak jak zwykle
do tego typu telefonów wysyłała ciąg impulsów elektrycznych. Zwykłe
telefony dzwoniły, elektryczne brzęczały a nowy telefon mówił. Każdy
telefon wykonywał zaprogramowane zadanie podyktowane tym
samym sygnałem z centrali.
Polimorfizm
C++ pozwala na wykorzystanie polimorfizmu funkcji i klas. Pod
tym samym identyfikatorem funkcji czy klasy może kryć się kilka
ich realizacji zależnych od „kontekstu”.
Rozwój C++
Jak tylko programowanie zorientowane obiektowo zyskało uznanie,
wówczas Bjarne Stroustrup rozbudował najbardziej popularny język
do tworzenia aplikacji, C, o właściwości niezbędne do tworzenia
obiektowego. W ten oto sposób powstało C++ i w bardzo krótkim
czasie stało się najbardziej popularnym językiem do rozwijania
aplikacji.
Prawdą jest, że C++ to rozbudowane C, każdy poprawny program w C
jest również prawidłowy w C++.
H. L. Mencken powiedział kiedyś o muzyce Wagnera:
„W rzeczywistości jest ona lepsza niż jej brzmienie”.
Takie rozumowanie może prowadzić do nieporozumień.
Różnica między C i C++ jest większa niż to widać na pierwszy
rzut oka.
C++, bardziej niż inne języki, wymaga od programisty
zaprojektowania programu przed napisaniem go. Oczywiście proste
problemy nie wymagają wielkiego wkładu w projektowanie. Jednak
duże zagadnienia, rozwijane codziennie przez zawodowych
programistów wymagają poświęcenia dużej ilości czasu na ich
właściwe przygotowanie, również na określenie czasu ich
powstawania i kosztów. Dobry projekt powoduje, że program jest
poprawny i zawiera niewiele błędów łatwych do poprawienia.
Pierwsze pytanie jakie programista powinien sobie postawić brzmi:
Jaki problem chcę rozwiązać?
Każdy program powinien mieć jasno określony, dobrze
postawiony cel.
Drugie ważne pytanie to:
Czy można tego dokonać bez uciekania się do pisania własnego
oprogramowania?
Ponowne użycie innego programu jest zazwyczaj lepszym
rozwiązaniem niż pisanie wszystkiego od nowa. Programista, który
stosuje te alternatywne rozwiązania znacznie ułatwia sobie pracę.
Szukanie tańszych rozwiązań do aktualnych problemów będzie
procentować w przyszłości.
C++, ANSI C++, Windows i inne
DOS, Windows, UNIX, MacOS, Linux systemy operacyjne.
C++ język programowania.
Ucząc się C++, poznajecie go jako język „przenośny”, nie odwołujący
się do żadnego konkretnego komputera, czy systemu operacyjnego.
Kompilator może być zintegrowany z edytorem tekstu lub może
wymagać użycia zewnętrznego edytora.
Pliki tworzone w edytorze nazywane są plikami źródłowymi i w C++
zazwyczaj zapisywane są z rozszerzeniem:
.CPP ; .CP lub .C
Kompilator i edytor
Przy zapisywaniu tekstu programu należy pamiętać, aby zachować go
jako zwykły plik tekstowy (bez informacji o formatowaniu).
Przykładami takich edytorów to:
• Notatnik z Windows;
• Edit z DOSa;
• VI czy Brief itd.
Kompilacja i łączenie kodu źródłowego
Plik źródłowy można nazwać w pewnym sensie zaszyfrowanym (nikt
kto nie zna C++, nie będzie w stanie powiedzieć, co on robi). Jednak
nadal jest on czytelny jedynie dla człowieka. Nie można go nazwać
programem w sensie pliku uruchamialnego – nie da się go uruchomić.
Aby przetworzyć plik źródłowy na program wykonalny, należy go
skompilować.
Jeżeli będziecie kompilować pliki źródłowe z linii poleceń systemu
operacyjnego powinniście wpisać:
bc <nazwa pliku>
Dla kompilatora Borland C++
tc <nazwa pliku>
cl <nazwa pliku>
bcc <nazwa pliku>
gcc <nazwa pliku>
Dla kompilatora Borland C++ dla
Windows
Dla kompilatora Borland Turbo C++
Dla kompilatora firmy Microsoft
Dla kompilatora pod Linuxem
Konsolidacja programu (ang. Linking)
Wynikiem procesu kompilacji jest plik obiektowy. Zazwyczaj ma on
rozszerzenie:
.OBJ.
Jednak nadal nie jest to plik możliwy do uruchomienia. Do
przekształcenia go w program wykonywalny niezbędny jest program
łączący (ang. linker).
Programy w C++ powstają zazwyczaj poprzez połączenie jednego lub
więcej plików .OBJ z jedną lub więcej bibliotekami. Biblioteki to zbiór
gotowych do dołączenia plików dostarczanych razem z kompilatorem.
Wszystkie kompilatory C++ są dostarczane ze zbiorem bibliotek
użytecznych funkcji (ewentualnie procedur) i klas, które można
wykorzystywać we własnych programach.
Funkcja to fragment kodu wykonujący pewne zadanie, np.
wypisujący coś na ekranie czy dodająca dwie liczby.
Klasa to zbiór danych wraz z funkcjami operującymi na nich.
Kompilacja w zintegrowanym środowisku
Większość nowoczesnych kompilatorów funkcjonuje na zasadzie
zintegrowanego środowiska. Zazwyczaj wystarczy wybrać opcję:
Kompliuj (ang. Compile, Build)
Z odpowiedniego menu. Często mamy do dyspozycji paski narzędzi
ze specjalnymi przyciskami uruchamiającymi kompilację.
Fazy powstawania programu
Start
Konie
c
Edycja plików źródłowych
Kompilacja
Linkowanie
Uruchomienie programu
Błędy kompilacji
?
Błędy
linkowania ?
Błędy
uruchomienia
T
T
T
F
F
F
#include <iostream.h>
main()
{
cout << "Hello world!" << endl;
return 0;
}
Pierwszy program
Efekt działania programu:
Jest
sygnałem
dla
preprocesora.
Zadaniem
preprocesora
jest
przejrzenie
tekstu
programu
i
znalezienie
wszystkich
odwołań
rozpoczynających się od
znaku #. W momencie
znalezienia tego symbolu
preprocesor
odpowiednio
modyfikuje tekst programu
i taki przerobiony tekst
przesyła do kompilatora.
To instrukcja preprocesora
mówiąca: „Następny tekst
to nazwa pliku. Znajdź ten
plik i wstaw go tutaj”.
Umieszczenie
nazwy
pliku
pomiędzy <…> oznacza: „szukaj
tego
pliku
w
miejscu
przeznaczonym dla plików takich
jak ten”.
Jeżeli
kompilator
jest
właściwie
skonfigurowany,
to
symbole
<
>
spowodują, że plik iostream.h odczytany
będzie z katalogu, w którym znajdują się
wszystkie pliki H (nagłówkowe). Plik
iostream.h (Input-Output-STREAM) jest
używany przez instrukcję cout, która służy
w
przykładowym
programie
do
wypisywania tekstu na ekranie.
Reasumując działanie pierwszej linii
sprowadza się do wstawienia
zawartości pliku iostream.h do
tekstu programu źródłowego.
#include <iostream.h>
main()
{
}
Każdy program w C++
musi
posiadać
funkcję
main(). Funkcja ta jest
szczególną funkcją gdyż
jest
ona
wykonywana
automatycznie na początku
każdego programu. Zwraca
ona zawsze wartość typu
int (całkowitego).
Obiekt cout oraz związany z nim cin
pozwalają na wypisywanie na wyjście (czyli
np. ekran) i czytanie z wejścia (np. z
klawiatury).
Wszystko co się znajduje za operatorem
przekierowania << zostanie wypisane na
ekranie. Uwaga tekst musi być z obu stron
ograniczony znakiem cudzysłowu!
Emulacja trybu tekstowego w Windows i
klasycznego środowiska programisty
Klasyczne środowisko i emulacja trybu tekstowego w Borland
C++
Klasyczne
środowisko
uruchomieniowe
(IDE
–
Integrated
Development Enviroment) w wersji Borland C++ 5.02
Domyślna konfiguracja zaraz po zainstalowaniu powoduje, że
skompilowanie i uruchomienie przykładowego programu o domyślnej
nazwie NONAME00 przebiega w trybie emulacji tekstowej trybu pracy
Windows. Choć w programie nie ma żadnej instrukcji dotyczącej
tworzenia okna aplikacji, Borland C++ przydziela najprostsze typowe
okno „do pisania”. Taki tryb pracy tekstowej jest nazywany EasyWin
mode.
Tworzenie okna w środowisku Windows odbywa się automatycznie
bez ingerencji programisty
Tryb DOS w Windows 9x i nowszych, czyli
aplikacje konsoli
W zależności od wersji systemu operacyjnego, to co w Windows 95
nazywa się Tryb MS-DOS (polecenie Start->Programs), to np. w
Windows 2000 Prof. nazywa się Command Prompt (Start-
>Programs->Accessories).
„Czarne okno do pisania” może się różnie nazywać, ale spełnia z
naszego punktu widzenia dokładnie tę samą rolę. Pozwala na
uruchamianie najprostszych programów przykładowych pisanych w C
lub C++, bez zaprzątania sobie głowy graficznymi gadżetami.
Aby w środowisku IDE Borland C++5.02 uzyskać na wyjściu aplikację
konsoli należy wykonać następujące czynności:
Z polecenia Project->New Project
Target Expert
W oknie
New Traget
z listy
Platform
wybieramy
DOS
(Standard)
Nie wszyscy wiedzą, że aplikacje konsoli potrafią tworzyć prostą grafikę.
Aplikacje konsoli mogą rysować
Skrót BGI ( Borland
Graphics Interface )
oznacza
technologię
opracowaną
dla
Borland C++ w latach
80.
Chociaż
minęło
sporo lat, tak napisane
programy
rysują
poprawnie nawet w
systemach
Wnidows
2000 czy XP.
Działanie przykładowego programu rysującego
Aplikacje konsoli w Borland C++ Builder 6.0
Zamykamy domyślny projekt poleceniem File-> Close All
Następnie z menu File->New->Other
Wybieramy
Console
Wizard
czyli kreator
aplikacji konsoli
Okno kreatora aplikacji konsoli
Działanie aplikacji konsoli w Borland C++
Builder 6.0
Aplikacje konsoli w Visual C++ 6.0
Konstrukcja środowiska Microsoft Visual C++ (PWB – Programmer’s
WorkBench, w odróżnieniu od IDE) jest podobna do opisanych
narzędzi firmy Inprise (dawniej Borland), ale ma pewną specyfikę.
Z menu wybieramy File ->
New
Wygodniej jest wybierać opcję
przykładowej aplikacji ponieważ
dla początkujących programistów
w tym środowisku czeka trochę
pułapek.
Informacja kreatora Visual
C++ o konfiguracji
projektu.
Automatycznie wygenerowany przez kreatora kod źródłowy
Rezultat działania pierwszego programu w C++ w VC+
+6.0