C++ implementálási alapok
Alapelv: modularizáció
-> C++ egy objektum orientált programozási nyelv, tehát a cél a kívánt
programkód implementálása minél kisebb, funkcionális működését ellenőrizhető
egységekkel.
Modularizáció
Alapvető szerkezeti eszköze: project file: több
különálló állomány használatát teszi lehetővé.
Célok:
1. procedurális: hasonló funkciójú
függvények elkülönítései
2. objektum orientált: osztálydefiníciók
elkülönítései
Előnyök: csoportos fejlesztés, áttekinthetőség,
újrahasznosítás
Implementációs megállapodások:
1. minden a program által használt állományt tartalmaz a
project fájl
2. állományok között ne legyen globális változó (ellenkezne a
modularitás értelmével)
3. forrásállományon belül globális változót csak nagyon
indokolt esetben használjunk
4. a fejállományokat az azt használó állományok inklúdolják
5. a megfelelő "könyvtárak" /(library) lásd.: prognyelvek 2/ elemeire való közvetlen hivatkozás a
"::" jellel lehetséges, de névtérbe is bevehető. leggyakoribb
a standard library (std::)
6. megállapodás szerint vegyük be a névtérbe az std -t, hiszen
gyakorlatilag arra építjük az első két félév programozását, ez mondhatjuk, hogy
a C++ (és nagyrészt a C) programozási nyelvi elemek metszete. (using namespace
std;)
Alapvető
szerkezet
Minden forrásfájlban megtalálható az ún. main függvény, melynek két paramétere az
indítási paraméterek száma (int argc) és a paramétereket tartalmazó tömb (char*
argc[]). Elemi alkalmazások fejlesztése 1 tantárgy
keretein belül hármas tagolódást kell mutatnia a függvénynek: adatok beolvasása, számítások elvégzése, majd az eredmény
kiírása, de esetenként ez összemosódhat.
Hibák
Implementációs jótanács: fordítani, fordítani,
fordítani, minél kisebb egységenként ellenőrizni a program helyes működését!
Hibafajták: fordítóidejű
és bug. A fordítóidejű problémát a
compiler jelzi, fatális esetben (error) nem is hoz létre futtatható állományt,
míg egyéb esetben figyelmeztetés (warning) mellett létrehozza azt. (Megjegyzés:
a fordító hibaüzenete a hiba észlelési helyét jelzi, nem azt, hogy mi és hol okozza!) A bug felderítése problémásabb, az
ugyanis a program elvi felépítéséből adódó hiba. Ilyenkor a nyomkövetés a legcélravezetőbb módja,
hogy lépésről lépésre nyomon követhessük a program működését.
A tárgy első két félévben
olyan programokat kellene implementálni, amelyek sem error, sem warning
fordítóidejű jelzést nem adnak.
Szintaxis
Vannak szintaktikai követelmények,
melyeket az adott nyelv tesz kötelezővé (szintaxis)
és a fordító kényszerít ki, valamint vannak megállapodások, amiket a
gyakorlatvezetők tesznek kötelezővé. Ez utóbbi a program funkcionális működését
nem befolyásolja.
Általános
szintaktikai megállapodások:
1. minden utasítást új sorba írunk, pontosvesszővel a végén,
kivéve a szimultán értékadásokat
2. blokkok után nem teszünk pontosvesszőt (kapcsoszárójellel
határoltak)
3. az állapottérváltozókat a main()
függvény elején deklaráljuk, a segédváltozókat a blokkjukban (ezt egyes
programozási nyelvek (pl ADA, C) meg is követelik)
4. a szimultán értékadásokat egy sorba írt egyszerű
értékadásokkal helyettesítjük
5. az elágazás ágait és a ciklusmagot blokkokba tesszük ({}),
kivéve, ha egy utasításból áll, akkor viszont egy sorba a szerkezeti
utasítással
6. többágú elágazást if()else if()...else() –el valósítunk meg (speciális esetben használható az ún.
switch is)
7. általában while ciklust, esetenként for -t és do-while -t
használunk
8. tabulátoros tagolással elkülönítjük a blokkokat
Absztrakt
programból C++ forráskódok implementálása
Típusmegfeleltetés:
az állapottérnek megfelelő (típushelyes) változókat deklarálunk
Probléma: nem minden
állapottérkomponensnek van megfelelő beépített típusa standard C++ -ban.
Kifejtését lásd lejjebb!
Algoritmus kódolása stuktogramm alapján, kívülről befelé
haladva
Eredmény megjelenítése
A típushelyesség problémája: az állapottér egyes komponenseinek lehet megfelelő
típusa C++ -ban, amit deklarálhatunk is, de a gyakorlatban általában származtatnunk
kell ezeket, illetve megszorításokat kell tennünk, hogy megfeleljenek a
típusspecifikációnak. Pl.: egész számok halmaza az állapottérkomponens, akkor
az "int" típusból képzett változó megfelelően reprezentálja az egész
számok halmazán értelmezett állapottérváltozót, de ha a feladat állapotterében pl. a páros egészek halmaza szerepel, akkor
kénytelenek vagyunk egy logikai megkötést végezni a bemenő adatok között, tehát
egy "int" típusú bemenő változót ellenőrizni kell, le kell szűkíteni
a megfelelő halmazra. (Gyakorlatilag ezt az absztrakt program specifikációjában
is elvégezhetjük úgy, hogy állapottér transzformációt hajtunk végre és az előfeltételbe bevesszük a szűkítést.) Egy másik példa,
ha egy két dimenziós, egész alapú koordinátarendszer pontjainak halmazát
akarjuk implementálni, ekkor kénytelenek vagyunk egyedi, származtatott típust
(jelen esetben rekord típust) használni, melybe két "int" típusú
változó kerül. (struct{int x, int y}). A fenti példák
mind integer (egész) típusra épülő típusmegvalósítások.
Megjegyzés: ebben a félévben
csak statikus reprezentációjú típusokat használunk (nem pointeres)...
Alapvető struktúrák, szolgáltatott típusműveletekkel:
struct: szelektorok szerinti
hivatkozás lehetősége
enum: felsorolás, ahol a típusértékek
között csak összehasonlító művelet létezik, amit a felsorolásban vett sorszámok
közötti általános relációk adnak
union: nincs típusmeghatározási
művelet, nem használjuk
Osztályok (class)
Ha saját, nem C++ által szolgáltatott típusműveletekre van szükség,
akkor osztályt (class) kell használni, ahol a típusdeklarációt és a
típusváltozókkal kapcsolatos metódusokat egy összefüggő modulban
implementálhatjuk.
Az osztály tehát a típusmegvalósítás eszköze. Elemeit
hozzáférhetőség szempontjából a következő csoportok valamelyikébe soroljuk: public (kívülről hozzáférhető), private (csak a saját, belső metódusok
használhatják), protected
(származtatott osztályok esetén nem érik el az osztály példányai). Kiemelt
fontosságú metódusai a konstruktor és
a destruktor, ezekről később még lesz
szó.
Általában külön forrásban/forrásokban
helyezzük el (.h, .cpp, hpp), egyforrású esetben a következő megállapodást
tartjuk be: a típus és metódusdeklarációs rész (osztálydeklaráció) a main() függvény
és egyébb függvénydeklarációk előtt, a metódusok konkrét definíciói
pedig a main() függvény után helyezkednek el!
Implementációs megállapodások:
1. public
-ban deklaráljuk a típusműveleteket
2. private
-ban deklaráljuk a típus változóit, melyekkel az osztály felvehet egy típusértéket reprezentáló állapotot
3. private
-ban deklaráljuk a kizárólag belső metódusok használatára szánt metódusokat
4. legalább
egy konstruktor -t definiálunk (feladata, hogy a reprezentáló elemeket olyan
értékekkel töltsük fel, hogy kielégítsék a típusinvariánst)
5. statikus
repr. oszt. esetén nincs szükség copy konstruktorra,
sem értékadás operátorra
6. statikus
repr. oszt. esetén akkor definiálunk destruktort az
alapértelmezett helyett, ha a konstruktorban használtunk olyan inicializáló
utasítást, melynek van lezáró párja (pl open-close)
7. beágyazott
definíciót csak ritkán és rövid metódusdefiníció esetén használunk
Függvények
Használata áttekinthető, tömörített
programot eredményez. Gyakran végrehajtott utasítássorozatokra javasolt eszköz.
A deklarációja meghatározza a visszatérési értékének típusát (vagy void, ha nincs visszatérési értéke), valamint
a várt paramétereket. Módosító jelek: &,
ami közvetlen paraméterátadást okoz és const,
ami megköveteli, hogy a végrehajtás során a változó értéke ne változzon meg.
Implementációs megállapodások
1. ha egy
kimenő adatra van szükség, akkor visszatérési értéket használunk, több kimenő
adat esetén void és paraméterátadást végzünk, kivéve, ha létezik kitüntetett visszatérési
érték (általában speciális logikai érték), ekkor azzal visszatérünk, a többit
átadjuk
2. mindig
legyen return utasítás
3. ha
programozási tételre vezetünk vissza, akkor a programozási tételeket önálló
blokkba implementáljuk
4. összetett
I/O műveleteket külön függvénybe implementáljuk
5. a függvénydeklarációt
a main() függvény előtt, a definíciót pedig utána
helyezzük el
Nem ellenőrzött anyag! Hiteles információt, valamint egyéb hasznos
segédanyagot a következő linkre kattintva találhat:
http://people.inf.elte.hu/gt/eaf/eaf1/eaf1.html.