w16


Projektowanie klas  c.d.
佛 og贸lne wskaz贸wki dotycz膮ce projektowania klas:
o wyodr臋bnienie klasy  odpowiedz na potrzeby 偶ycia
(obs艂uga rozwi膮zania konkretnego problemu)
o zwykle nie uda si臋 utworzy膰 idealnej definicji  jej
precyzowanie nast臋puje w trakcie pracy
o zachowuj prostot臋  zaczynaj od ma艂ych i prostych
obiekt贸w o oczywistym przeznaczeniu
o zacznij programowa膰  sprawdz w dzia艂aniu
proponowany projekt
Projektowanie klas  przyk艂ad
佛 cel: napisanie programu u艂atwiaj膮cego zarz膮dzaniem
portfelem papier贸w warto艣ciowych
佛 pytanie  jak reprezentowa膰 takie papiery  co ma by膰
podstawowym obiektem opisu; mo偶liwo艣ci:
o obiekt reprezentuje pojedynczy udzia艂
o obiekt  zapis puli udzia艂贸w jednej sp贸艂ki przez
b臋d膮cych w posiadaniu jednej osoby
佛 wyb贸r drugiej mo偶liwo艣ci  klasa Akcje;
佛 operacje wykonywane na udzia艂ach:
o nabycie udzia艂贸w nowej sp贸艂ki
o sprzeda偶 pewnej ilo艣ci udzia艂贸w
o zakup pewnej ilo艣ci udzia艂贸w
o aktualizacja warto艣ci pojedynczego udzia艂u
o wy艣wietlenie informacji o posiadanych udzia艂ach
佛 powy偶sza lista okre艣la podstawowy publiczny interfejs
klasy Akcje
佛 lista informacji, kt贸re powinny zawiera膰 obiekty klasy
o nazwa sp贸艂ki
o liczba posiadanych udzia艂贸w
o warto艣膰 jednostkowa udzia艂u
o 艂膮czna warto艣膰 akcji danej sp贸艂ki w posiadaniu danej
osoby
佛 deklaracje klasy Akcje:
class Akcje // deklaracja klasy
{
private:
char firma[30];
int udzialy;
double cena;
double wart_calk;
void ustal_wart() { wart_calk = udzialy * cena; }
public:
void nabycie(const char* co,int ile, double po_ile);
void sprzedaj(int ile, double po_ile);
void kupuj(int ile, double po_ile);
void aktualizyj(double nowa_cena);
void pokaz();
};
佛 cechy deklaracji klasy:
o dane ukryte, niedost臋pne poza klas膮
o publiczne funkcje sk艂adowe  po艣rednik mi臋dzy
programem a obiektem klasy (publiczny interfejs)
o oddzielenie publicznego interfejsu od szczeg贸艂贸w
implementacji (zazwyczaj implementacja metod klasy
 poza cia艂em klasy, w oddzielnym pliku)
o ukrywanie danych  zwolnienie u偶ytkownik贸w od
konieczno艣ci znajomo艣ci wewn臋trznej reprezentacji
danych
o prywatna metoda klasy : ustal_wart()
Implementacja metod:
void Akcje::nabycie(const char * co, int ile, double po_ile)
{
strncpy(firma, co, 29);
firma[29] = '\0';
if (ile < 0)
{
std::cerr << "Liczba udzialow nie moze byc ujemna; "
<< "ustalam liczbe udzialow " << firma << " na 0.\n";
udzialy = 0;
}
else
udzialy = ile;
cena = po_ile;
ustal_wart();
}
void Akcje::kupuj(int ile, double po_ile)
{
if (ile < 0)
{
std::cerr << "Liczba nabywanych udzialow nie moze byc ujemna "
<< "Transakcja przerwana.\n";
}
else
{
udzialy += ile;
cena = po_ile;
ustal_wart();
}
}
void Akcje::sprzedaj(int ile, double po_ile)
{
using std::cerr;
if (ile < 0)
{
cerr << "Liczba sprzedawanych udzialow nie moze byc ujemna. "
<< "Transakcja przerwana.\n";
}
else if (ile > udzialy)
{
cerr << "Nie mozesz sprzedac wiecej udzialow, niz posiadasz! "
<< "Transakcja przerwana.\n";
}
else
{
udzialy-= ile;
cena = po_ile;
ustal_wart();
}
}
void Akcje::aktualizuj(double pr)
{
cena = pr;
ustal_wart();
}
void Akcje::pokaz()
{
using std::cout;
using std::endl;
cout << "Spolka: " << firma
<< " Liczba udzialow: " << udzialy << endl
<< " Cena udzialu: " << cena << " zl"
<< " Laczna wartosc udzialow: " << wart_calk << " zl" << endl;
}
佛 analiza dzia艂ania programu wykorzystuj膮cego dzia艂anie
klasy Akcje:
Akcje p1;
p1.kupuj(10,15.0);
p1.pokaz;
Spolka: 羨_艁" Liczba udzialow: 2009249824
Cena udzialu: 3.7 zl Laczna wartosc udzialow: 7.43422e+009 zl
佛 problem  inicjalizacja zmienych  mo偶liwa tylko w funkcji
nabycie; je偶eli nie jest to pierwsza operacja na
zmiennej, to mamy problem
佛 rozwi膮zanie  zast膮pienie funkcji nabycie konstruktorem
佛 inne ulepszenia
o wykorzystanie klasy string do reprezentacji 艂a艅cucha
znak贸w
o funkcje sk艂adowe zale偶ne od dw贸ch obiekt贸w
o wykorzystanie tablic obiekt贸w
o struktura plik贸w  definicji i implementacji klasy,
plik贸w zastosowa艅
o wykorzystanie sta艂ych o zasi臋gu klasy
o separacja interfejs - implementacja
佛 problem inicjalizacji  wprowadzamy konstruktory
o konstruktor zast臋puj膮cy funkcj臋 nabycie
o konstruktor domy艣lny
class Akcje {
. . .
public:
Akcje(const char* co,int ile=0, double po_ile=0.0);
Akcje( );
};
佛 w poprzedniej wersji  pole firma: C-string o okre艣lonej
d艂ugo艣ci
o problem  ograniczenie na ilo艣膰 znak贸w  obci臋cia
d艂ugo艣ci albo niewykorzystanie miejsca
o rozwi膮zanie  zastosowanie klasy string
class Akcje {
private:
std:string firma;
. . .
};
佛 problem  mamy kilka obiekt贸w typu Akcje  chcemy
por贸wna膰 dowoln膮 ich par臋 by okre艣li膰, kt贸ry z nich ma
wi臋ksz膮 warto艣膰 rynkow膮
佛 rozwi膮zanie  funkcja kt贸ra zale偶y od dw贸ch obiekt贸w
podlegaj膮cych por贸wnaniu
佛 Akcje drozsza(Akcje & o1, Akcje & o2)
佛 problem dost臋pu do danych  najlepiej, by by艂a to funkcja
sk艂adowa klasy Akcje
佛 wywo艂anie takich funkcji  zawsze na rzecz obiektu klasy:
sk艂adnia takiego wywo艂ania:
Akcje o1,o2,w;
w=o1.drozsza(o2);
lub
w=o2.drozsza(o1);
佛 jak przekaza膰 odpowiedz funkcji drozsza ?
o najlepiej  przekaza膰 referencj臋 obiektu kt贸ry
reprezentuje wi臋ksz膮 warto艣膰 udzia艂贸w, to sugeruje
prototyp funkcji postaci:
const Akcje & drozsza(const Akcje & druga) const;
o funkcja korzysta z dw贸ch obiekt贸w  jawnie z tego,
kt贸ry jest jej argumentem (druga), niejawnie z tego,
na rzecz kt贸rego zosta艂a wywo艂ana
o jak zwr贸ci膰 referencj臋 obiektu, na rzecz kt贸rego
funkcja jest wywo艂ana?
o rola wskaznika this
const Akcje & drozsza(const Akcje & druga)
{
if(druga.wart_calk>= wart_calk) return druga;
else return *this;
}
佛 zapis klasy  dwa pliki:
o plik nag艂贸wkowy klasy
// plik Akcje.h - deklaracja klasy
#ifndef AKCJE_h_
#define AKCJE_h_
class Akcje // deklaracja klasy
{
private:
static const int ROZMIAR = 30;
std::string firma;
int udzialy;
double cena;
double wart_calk;
void ustal_wart() { wart_calk = udzialy * cena; }
public:
Akcje( );
Akcje(const char* co,int ile=0, double po_ile=0.0);
const Akcje & drozsza(const Akcje & druga);
void kupuj(int ile, double po_ile);
void sprzedaj(int ile, double po_ile);
void aktualizuj(double nowa_cena);
void pokaz();
void pokaz_bez_0();
};
#endif
o plik z implementacj膮 funkcji sk艂adowych:
#include
#include
#include "akcje.h"
using namespace std;
Akcje::Akcje(const char * co, int ile, double po_ile)
{
firma=co;
if (ile < 0)
{
cerr << "Liczba udzialow nie moze byc ujemna; "
<< "ustalam liczbe udzialow w " << firma << " na 0.\n";
udzialy = 0;
}
else
udzialy = ile;
cena = po_ile;
ustal_wart();
}
Akcje::Akcje( )
{
firma="brak nazwy";
udzialy=0;
cena = 0.0;
ustal_wart();
}
const Akcje & Akcje::drozsza(const Akcje & druga)
{
if(druga.wart_calk>= wart_calk) return druga;
else return *this;
}
void Akcje::kupuj(int ile, double po_ile)
{
if (ile < 0)
{
cerr << "Liczba nabywanych udzialow nie moze byc ujemna. "
<< "Transakcja przerwana.\n";
}
else
{
udzialy += ile;
cena = po_ile;
ustal_wart();
}
}
void Akcje::sprzedaj(int ile, double po_ile)
{
using std::cerr;
if (ile < 0)
{
cerr << "Liczba sprzedawanych udzialow nie moze byc ujemna. "
<< "Transakcja przerwana.\n";
}
else if (ile > udzialy)
{
cerr << "Nie mozesz sprzedac wiecej udzialow, niz posiadasz! "
<< "Transakcja przerwana.\n";
}
else
{
udzialy-= ile;
cena = po_ile;
ustal_wart();
}
}
void Akcje::aktualizuj(double po_ile)
{
cena = po_ile;
ustal_wart();
}
void Akcje::pokaz()
{
string nazwa(firma);
nazwa.resize(ROZMIAR);
string ss(ROZMIAR+30,'-');
cout << ss << "\n"
<<"Spolka: " << nazwa
<< " Liczba udzialow: " << udzialy << endl
<< " Cena udzialu: " << cena << " zl"
<< " Laczna wartosc udzialow: " << wart_calk << " zl" << endl;
}
void Akcje::pokaz_bez_0( )
{
if(wart_calk > 0.0)
pokaz( );
}
o funkcja pokaz( )  obci臋cie i normalizacja d艂ugo艣ci
nazwy firmy w wydruku
o funkcja pokaz  prezentuje tylko obiekty o ca艂kowitej
warto艣ci > 0
o wykorzystanie sta艂ej o zasi臋gu klasy ROZMIAR
佛 plik klienta - wykorzystanie definicji klasy
o w艂膮czenie nag艂贸wka i pliku implementacji klasy
o zastosowanie tablicy
o inicjalizacja tablic obiekt贸w  typowa sk艂adnia inicjalizacja
tablicy: uj臋ta w nawiasy klamrowe lista wyra偶e艅
inicjalizuj膮cych (wywo艂a艅 konstruktor贸w dla poszczeg贸lnych
element贸w tablicy)
o u偶ycie konstruktora domy艣lnego
#include "akcje.cpp"
#include "akcje.h"
int main()
{
const int ROZ_PORTFEL = 10;
Akcje portfel[ROZ_PORTFEL] = {
Akcje("KGHM", 70,136.6),
Akcje("Zelmer", 300, 27.0),
Akcje("Comarch", 60,57.10)
};
cout << "Sklad portfela: \n";
cout.setf(ios_base::fixed); // format #.##
cout.precision(2); // format #.##
cout.setf(ios_base::showpoint); // format #.##
for(int st=0; st < ROZ_PORTFEL; st++)
portfel[st].pokaz_bez_0(); // tylko akcje o warto艣ci>0
portfel[1].kupuj(245, 33.10);
Akcje best=portfel[0];
for(int st=0; st < ROZ_PORTFEL; st++)
best=best.drozsza(portfel[st]);
cout << "\n\n\nNajcenniejszy walor:\n";
best.pokaz();
}
Projektowanie klas  interfejs, implementacja
佛 publiczne sk艂adowe klasy  interfejs klasy
佛 zmiany w interfejsie  zmieniaj膮 spos贸b dzia艂ania klasy, list臋
dost臋pnych dzia艂a艅
佛 prywatne sk艂adowe klasy oraz definicje funkcji sk艂adowych 
implementacja klasy
佛 zmiany w implementacji  wp艂ywaj膮 na wewn臋trzne
szczeg贸艂y dzia艂ania klasy, nie wp艂ywaj膮 na spos贸b
wykorzystania klasy
Abstrakcyjne typy danych
佛 opis typu danych dokonany w spos贸b uog贸lniony (bez
uwarunkowa艅 j臋zyka programowania i szczeg贸艂贸w
implementacji
佛 przyk艂ad - stos
佛 wymagane w艂asno艣ci:
o zdolno艣膰 do przechowania pewnej ilo艣ci element贸w
(rodzaj kontenera)
o mo偶liwo艣膰 wykonania operacji:
偶 tworzenie pustego stosu
偶 od艂o偶enie elementu na stos
偶 zdj臋cie elementu ze stosu
偶 sprawdzenie, czy stos jest pusty
偶 sprawdzenie, czy stos jest pe艂ny
佛 realizacja  deklaracja klasy
o operacje  publiczne funkcje sk艂adowe (interfejs)
o dane stosu  przechowywane w prywatnych danych
klasy
o swoboda w wyborze pojemnika danych (tablica
statyczna, tablica alokowana dynamicznie, lista)
o interfejs przes艂ania dok艂adn膮 reprezentacj臋
wewn臋trzn膮 stosu
o nasz wyb贸r: statyczna tablica, ustalony rozmiar
maksymalny, stan wype艂nienia  indeks elementu
szczytowego stosu
o staramy si臋 uzyska膰 niezale偶no艣膰 od typu zawarto艣ci
stosu
佛 definicja stosu  plik nag艂贸wkowy
// definicja klasy stos
#ifndef STOS_H_
#define STOS_H_
typedef unsigned int Item;
class Stos {
enum {MAX = 10}; // rozmiar maksymalny
Item items[MAX]; // tablica przechowuj膮ca elementy
int top; // indeks elementu na szczycie
public:
Stos();
bool jest_pusty( ) const;
bool jest_pelny( ) const;
bool poloz(const Item & item);
bool zdejm(Item & item);
};
#endif
佛 definicja stosu  implementacja metod
#include "stos.h"
typedef unsigned int Item;
Stos::Stos() //tworzy pusty stos
{
top=0;
}
bool Stos::jest_pusty() const
{
return top==0; //pusty, gdy indeks szczytu ma wartosc 0
}
bool Stos::jest_pelny() const
{
return top==MAX; //pe艂ny, gdy indeks szczytu = MAX
}
bool Stos::poloz(const Item & item)
{
if(top {
items[top++]=item; //wpisuje warto艣膰 elementu
return true; //zwraca TRUE
}
else return false; // stos pe艂ny, nic nie robimy
}
bool Stos::zdejm(Item & item)
{
if(top>0) //mo偶liwe, gdy stos niepusty
{
item=items[--top]; //zwracamy element stosu przez argument
return true; // O.K., uda艂o si臋
}
else return false; //stos pusty, nic nie robimy
}
佛 interfejs publiczny przes艂ania spos贸b implementacji
stosu (mo偶liwa zmiana implementacji bez zmiany
sposobu korzystania z klasy
佛 spos贸b definicji stosu nie zale偶y od typu danych w nim
przechowywanych  by go zmieni膰 wystarczy
modyfikacja instrukcji typedef
佛 definicja stosu  implementacja metod
Przyk艂ad wykorzystania:
#include
#include "stos.h"
#include "stos.cpp"
using namespace std;
int main(int argc, char *argv[])
{
Stos karty;
Item pp;
char z;
cout << "Nacisnij D by wczytac nastepna karte \n"
<< "P by przetworzyc karte, lub E by zakonczyc.\n";
while(cin >>z && toupper(z) != 'E')
{
while(cin.get() != '\n')
continue;
if(!isalpha(z))
{
cout << '\a';
continue;
}
switch(toupper(z))
{
case 'D': cout << "Podaj nr albumu: ";
cin >> pp;
if(karty.jest_pelny())
cout << "Stos pelny!\n";
else
karty.poloz(pp);
break;
case 'P': if (karty.jest_pusty())
cout << "Stos pusty!\n";
else
{
karty.zdejm(pp);
cout<< "Karta nr " << pp << " zdjeta\n";
}
break;
}
cout << "Nacisnij D aby wczytac nastepna karte \n"
<< "P by przetworzyc karte, lub E by zakonczyc.\n";
}
cout << "No to tyle na dzis !!!\n";
system("PAUSE");
return EXIT_SUCCESS;
}


Wyszukiwarka

Podobne podstrony:
cs w16
w16
Microsoft Word W16 pochodne zlozone funkcji 2 zm
W16 R贸偶niczkowanie funkcji
w16
Aire W16
E Pawlowski wyklad ME EINS 2013 w16
W16(1)
w16 konwersje
w16 Koncowe fazy ewolucji
w16
w16

wi臋cej podobnych podstron