Kategorie materiałów Informatyka

Przedmiot: C++ Dla Zaawansowanych Wróć do kategorii

LEKCJA 30. Wymiana danych między obiektami

plik Pobierz LEKCJA 30. Wymiana danych miedzy obiektami.txt

LEKCJA 30: WYMIANA DANYCH MIĘDZY OBIEKTAMI.  ________________________________________________________________  W trakcie tej lekcji dowiesz się, jak można wymieniać dane i  informacje pomiędzy różnymi obiektami.  ________________________________________________________________   Hermetyzacja danych jest cenną zdobyczą, ale od czasu do czasu  obiekty powinny dokonywać pomiędzy sobą wymiany informacji,  także tych wewnętrznych - prywatnych. Ten problem może sprawiać  programiście trochę kłopotów - należy zatem poświęcić mu trochę  uwagi.   DOSTĘP DO DANYCH PRZY POMOCY FUNKCJI KATEGORII friend.   Aby wyjaśnić mechanizmy dostępu do danych obiektów będziemy  potrzebować:   * wielu obiektów;  * danych prywatnych obiektów (dostęp do publicznych,  "niezakapsułkowanych" danych jest prosty i oczywisty);  * funkcji o specjalnych uprawnieniach.  Takie funkcje o specjalnych uprawnieniach - z możliwością  odwoływania się do prywatnych danych wielu obiektów (a nie tylko  swojego) muszą w C++ posiadać status "friend" (ang. friend -  przyjaciel).   Nasz przykładowy program będzie operował tablicą złożoną z  obiektów klasy Licznik.   class Licznik {    char moja_litera;    int ile; public:    void Inicjuj_licznik(char);    void Skok_licznika(void);    void Pokazuj(); };    ...  Licznik TAB[MAX];  Obiekty - liczniki będą zliczać wystąpienie (każdy swojego)  określonego znaku w strumieniu znaków wejściowych (wczytywanym z  klawiatury). Tablica będzie się składać z MAX == 26 elementów -  obiektów - liczników, po jednym dla każdej dużej litery  alfabetu. Tablica będzie nazywać się TAB[26]. Po zadeklarowaniu:   nazwa_klasy TAB[MAX];   kolejne obiekty będą się nazywać:   nazwa_klasy Obiekt1 == TAB[0];       //Licznik 1 - 'A' nazwa_klasy Obiekt2 == TAB[1];       //Licznik 2 - 'B'  ...                                    ... nazwa_klasy ObiektN == TAB[N-1];   Po wprowadzeniu znaku z klawiatury wywołamy wbudowaną do każdego  obiektu funkcję Skok_licznika(), która doda jedynkę do  wewnętrznego licznika obiektu. Wywołując funkcję zastosujemy  zamiast typowej składni   ObiektK.Skok_licznika();   odpowiadającą jej w tym wypadku notację   TAB[i].Skok_licznika();  Powinniśmy jeszcze przed wywołaniem funkcji sprawdzić, czy znak  jest dużą literą alfabetu. W przykładowym programie zrobimy to  tak:    ...   cin >> znak;                     //Pobranie znaku z klawiatury   for(int i = 0; i < 26; i++)      {         if(i == (znak - 'A')) TAB[i].Skok_licznika();       }  ...  Dzięki temu wewnętrzny licznik obiektu TAB[2] zostanie  powiększony tylko wtedy, gdy znak - 'A' == 2 (znak jest literą  C, bo 'C' - 'A' == 2).   Można to zapisać skuteczniej. ...    cin >> znak;    TAB[znak - 'A'].Skok_licznika();    //Inkrementacja licznika   ...  bądź jeszcze krócej:    ...    TAB[getch() - 'A'].Skok_licznika();   ...  Istnieje tu wszakże niebezpieczeństwo próby odwołania się do  nieistniejącego elementu tablicy, przed czym powinniśmy się  wystrzegać.  W wyniku działania programu otrzymamy zliczoną ilość  występowania danej litery w strumieniu znaków wejściowych.   [P107.CPP]    # include <ctype.h>            //prototyp toupper()  # include <iostream.h>     class Licznik  {     char moja_litera;     int ile;  public:     void Inicjuj(char);     void Skok_licznika();     void Pokazuj();  };     void Licznik::Inicjuj(char z)   {     moja_litera = z;     ile = 0;   }     void Licznik::Skok_licznika(void)   {     ile++;   }     void Licznik::Pokazuj(void)   {     cout << "Znak " << moja_litera << " wystapil "          << ile << " razy" << '\n';   }  main()   {   const MAX = 26; Licznik TAB[MAX];   register int i;     /* inicjujemy liczniki:  -------------------------------*/     for(i = 0; i < MAX; i++)      {        TAB[i].Inicjuj('A' + i);      }  /* pracujemy - zliczamy: -------------------------------*/    cout << "Wpisz ciag zankow zakonczony kropka [.]" << '\n';  for(;;)     { char znak;      cin >> znak;      if(znak == '.') break;      for(i = 0; i < MAX; i++)          {            if(i == (znak - 'A')) TAB[i].Skok_licznika();          }     }  /* sprawdzamy: ----------------------------------------*/    char sprawdzamy;  cout << '\n' << "Podaj znak do sprawdzenia: " << '\n';   cin >> sprawdzamy;  cout << "Wyswietlam wyniki zliczania: \n";     TAB[toupper(sprawdzamy) - 'A'].Pokazuj();     return 0;   }    Jeśli chcielibyśmy zliczyć ilość wszystkich wprowadzonych  znaków, powinniśmy zsumować dane pobrane od wielu obiektów.   Jeśli dane przechowywane w obiektach mają status danych  prywatnych, to dostęp do tych danych może być utrudniony. Do  tego momentu dostęp do danych prywatnych obiektu mogliśmy  uzyskać tylko posługując się autoryzowaną do tego metodą -  własną funkcją wewnętrzną tegoż obiektu. Ale wtedy nie mieliśmy  dostępu do danych innych obiektów a tylko do jednego -  "własnego" obiektu funkcji. Jeśli zatem chcielibyśmy zsumować  zawartości wielu obiektów - liczników, to należy do tego  zastosować tzw. funkcję "zaprzyjaźnioną" - friend function.  Jeśli deklarując funkcję zastosujemy słowo kluczowe friend, to  taka zaprzyjaźniona z klasą funkcja uzyska prawo dostępu do  prywatnych elementów danej klasy. Zadeklarujemy taką przykładową  zaprzyjaźnioną funkcję o nazwie Suma(). Funkcja będzie pobierać  jako parametr ilość obiektów do zsumowania i sumować zawartości  wewnętrznych liczników obiektów.   const MAX = 26;  class Licznik  {     char moja_litera;     int ile;  public:     void Inicjuj(char);     void Skok_licznika();     void Pokazuj();    friend int Suma(int);  } TAB[MAX];  Zadeklarowana w taki sposób zaprzyjażniona funkcja ma prawo  dostępu do prywatnych elementów wszystkich obiektów klasy  Licznik. Typowe zastosowanie funkcji typu friend polega właśnie  na dostępie do danych wielu różnych obiektów. Powinniśmy  zsumować zawartość pól   TAB[i].ile   dla wszystkich obiektów (od i = 0 aż do i = MAX). Zwróć uwagę,  że definiując funkcję Suma() nie stosujemy powtórnie słowa  kluczowego friend. A oto definicja:   int Suma(int ilosc_obiektow)  {        int i, suma = 0;     for(i = 0; i < ilosc_obiektow; i++)        suma += TAB[i].ile;         return (suma);  }   Dzięki zastosowaniu słowa "friend", funkcja Suma() jest  zaprzyjaźniona ze wszystkimi 26 obiektami, ponieważ wszystkie  obiekty należą do tej klasy, w której zadeklarowaliśmy funkcję:  class ...  {   ... friend int Suma(...);   ...  } ... ;   Tablica TAB[MAX] złożona z obiektów klasy Licznik została  zadeklarowana nazewnątrz funkcji main() ma więc status tablicy  GLOBALNEJ. Funkcja Suma() ma dostęp do prywatnych danych  wszystkich obiektów, możemy więc zastosować ją w programie w  następujący sposób:  [P108.CPP]  # include <ctype.h> # include <iostream.h>   class Licznik  {     char moja_litera;     int ile;  public:     void Inicjuj(char);     void Skok_licznika();     void Pokazuj();    friend int Suma(int);  }  const MAX = 26; Licznik TAB[MAX]; register int i;    main()   {   /* inicjujemy liczniki: -------------------------------*/    for(i = 0; i < MAX; i++)      {        TAB[i].Inicjuj('A' + i);      }  /* pracujemy - zliczamy: -------------------------------*/    cout << "Wpisz ciag zankow zakonczony kropka [.]" << '\n';  for(;;)     { char znak;      cin >> znak;      if(znak == '.') break;      for(i = 0; i < MAX; i++)          {            if(i == (znak - 'A')) TAB[i].Skok_licznika();          }     }  /* sprawdzamy: ----------------------------------------*/    char sprawdzamy;  cout << '\n' << "Podaj znak do sprawdzenia: " << '\n';   cin >> sprawdzamy;  cout << "Wyswietlam wyniki zliczania: \n";     TAB[toupper(sprawdzamy) - 'A'].Pokazuj();     cout << "\n Wszystkich liter bylo " << Suma(MAX);  return 0;   }   void Licznik::Inicjuj(char zn)   {     moja_litera = zn;     ile = 0;   }     void Licznik::Skok_licznika(void) { ile++; }    void Licznik::Pokazuj(void)   {     cout << "Znak " << moja_litera << " wystapil "          << ile << " razy" << '\n';   }   int Suma(int ilosc_obiektow)  {        int i, suma = 0;     for(i = 0; i < ilosc_obiektow; i++)        suma += TAB[i].ile;         return (suma);  }   Tak działa funkcja typu friend. Zwróćmy tu uwagę, że funkcja  taka nie jest traktowana dokładnie tak samo, jak metoda  wchodząca w skład klasy i obiektu. Metoda, czyli "własna"  funkcja obiektu odwołuje się do jego pola (danych) w taki  sposób:   void Licznik::Skok_licznika(void)  {      ile++;                 //Wiadomo o ktory obiekt chodzi  }   Funkcja klasy friend odwołuje się do pól obiektów tak:   int Suma(int liczba)  {   ...      suma += TAB[i].ile; /* - wymaga dodatkowo wskazania, o który obiekt chodzi - */ }   Należy pamiętać, że dla funkcji kategorii friend wszystkie  obiekty należące do danej klasy mają status public - są  dostępne.   O ZAPRZYJAŹNIONYCH KLASACH.   W C++ mogą być zaprzyjaźnione ze sobą wzajemnie także klasy.  Pozwala to metodom zdefiniowanym wewnątrz jednej z klas na  dostęp do prywatnych danych obiektów innych klas. W przypadku  zaprzyjaźnionych klas słowem kluczowym friend poprzedzamy nazwę  klasy (a nie każdej zaprzyjaźnionej metody z osobna, choć  zamierzony skutek właśnie na tym polega). Oto praktyczny  przykład zaprzyjaźnionych klas.   [P109.CPP]  # include <iostream.h>    class Data1;          //Deklaracja (a nie definicja!) klasy  class TEZ_DATA  {    int dz, rok;  public:    TEZ_DATA() {}    TEZ_DATA(int d, int y) { dz = d; rok = y;}    void Pokazuj() {cout << '\n' << rok << '-' << dz;}    friend Data1;                       //"zaprzyjazniona" klasa };   class Data1                           //Tu DEFINICJA klasy {    int mc, dz, rok;  public:    Data1(int m, int d, int y) { mc = m; dz = d; rok = y; }    operator TEZ_DATA();  };    static int TAB[] = {31,28,31,30,31,30,31,31,30,31,30,31};    /* ---- funkcja - metoda konwersji - definicja ----------- */  Data1::operator TEZ_DATA(void)  {    TEZ_DATA DT_Obiekt(0, rok);    for (int i = 0; i < mc-1; i++)    DT_Obiekt.dz += TAB[i];    DT_Obiekt.dz += dz;    return DT_Obiekt;  }    main()  {    Data1 dt_Obiekt(11,17,89);    TEZ_DATA DT_Obiekt;    DT_Obiekt = dt_Obiekt;    DT_Obiekt.Pokazuj();   return 0; }    Zaprzyjaźnione są klasy Data1 i TEZ_DATA. Dzięki temu metody  zadeklarowane wewnątrz zaprzyjaźnionej klasy Data1 mają dostęp  do prywatnych danych obiektów klasy TEZ_DATA. Ponieważ klasa to  nowy formalny typ danych, a obiekt to dane takiego nowego typu,  nic nie stoi na przeszkodzie, by obiekty przekazywać do funkcji  jako argumenty (tak jak wcześniej obiekty typów typowych - int,  float itp.).   W C++ mamy jeszcze jedną metodę wymiany danych. Możemy nadać  elementom klas i obiektów status static (statyczny).   WYMIANA INFORMACJI PRZY POMOCY DANYCH STATYCZNYCH.   Jeśli element klasy został zadeklarowany jako element statyczny  (przy pomocy słowa kluczowego static), to bez względu na to jak  wiele obiektów danej klasy utworzymy, w pamięci będzie istnieć  TYLKO JEDEN EGZEMPLARZ (kopia) tego elementu. W przykładowym  programie z obiektami-licznikami możemy osiągnąc taki efekt  nadając zmiennej ile (stan licznika) status static int ile:   class Licznik {      char moja_litera;       static int ile;      ...  };   Jeśli utworzymy wiele obiektów takiej klasy, to wszystkie te  obiekty będą posługiwać się tą samą (wspólną!) zmienną ile. Dla  przykładu, jeśli zechcemy zliczać ile razy w strumieniu danych  wejściowych pojawiły się np. znaki 'a' , 'b' i 'c', możemy  utworzyć trzy obiekty - liczniki: licznik_a, licznik_b i  licznik_c. wszystkie te liczniki będą posługiwać się wspólną  zmienną statyczną ile:   class Licznik { public:       char moja_litera;       static int ile;      Licznik(char);               //Konstruktor  ... };   Do zainicjownia obiektów posłużymy się konstruktorem. Deklaracja  obiektu spowoduje automatyczne wywołanie kostruktora i  zainicjowanie obiektu w pamięci. Przy okazji przekazujemy  obiektom znaki do zliczania.   Licznik licznik_a('a'), licznik_b('b'), licznik_c('c');   Jeśli teraz w strumieniu wejściowym pojawi się któraś z  interesujących nas liter (a, b, bądź c), zostanie wywołana  właściwa wersja metody Skok_licznika():   int main(void)  {    char litera;   ...   cin >> litera;   ...    if(litera == licznik_a.moja_litera) licznik_a.Skok_licznika();    if(litera == licznik_b.moja_litera) licznik_b.Skok_licznika();   ...  }  Zmienna ile jest zmienną statyczną, więc wsztstkie trzy funkcje  dokonają inkrementacji zmiennej znajdującej się pod tym samym  fizycznym adresem pamięci. Jeśli dla wszystkich obiektów danej  klasy jakaś zmienna oznacza zawartość tego samego adresu ...

Ciąg dalszy w pliku do pobrania.

Wkuwanko.pl jako podmiot świadczący usługę hostingu materiałów edukacyjnych nie ponosi odpowiedzialności za ich zawartość.

Aby zgłosić naruszenie prawa autorskiego napisz do nas.

ikona Pobierz ten dokument

Wróć do kategorii

wkuwanko.pl

Wasze komentarze: dodaj komentarz

  • Nie ma jeszcze komentarzy do tego materiału.

Materiały w kategorii C++ Dla Zaawansowanych [22]

  • podgląd pobierz opis LEKCJA 25. Przykład obiektu
  • podgląd pobierz opis LEKCJA 27. Dziedziczenie
  • podgląd pobierz opis LEKCJA 28. Dziedziczenie złożone
  • podgląd pobierz opis LEKCJA 29. Funkcje i overloading
  • podgląd pobierz opis LEKCJA 30. Wymiana danych między obiektami
  • podgląd pobierz opis LEKCJA 31. Przekazanie obiektów jako argumentów do funkcji
  • podgląd pobierz opis LEKCJA 33. Wskaźniki do obiektów
  • podgląd pobierz opis LEKCJA 34. Overloading operatorów
  • podgląd pobierz opis LEKCJA 35. O zastosowaniu dziedziczenia
  • podgląd pobierz opis LEKCJA 36. Funkcje wirtualne i klasy abstrakcyjne
  • podgląd pobierz opis LEKCJA 37. Jak komputer dysponuje swoimi zasobami w środowisku tekstowym (DOS)
  • podgląd pobierz opis LEKCJA 38. Programowanie dla Windows
  • podgląd pobierz opis LEKCJA 39. Wykorzystanie standardowych zasobów Windows
  • podgląd pobierz opis LEKCJA 40. Struktura programu proceduralno-zdarzeniowego
  • podgląd pobierz opis LEKCJA 41. Jak tworzy się aplikację dla Windows
  • podgląd pobierz opis LEKCJA 42. Kompilaroty specjalnie dla Windows
  • podgląd pobierz opis LEKCJA 43. Elementy sterujące i zarządzanie programem
  • podgląd pobierz opis LEKCJA 44. Okna dialogowe
  • podgląd pobierz opis LEKCJA 45. Dołączanie zasobów - menu i okienka dialogowe
  • podgląd pobierz opis LEKCJA 46. Programy obiektowo-zdarzeniowe
[ Misja ] [ Regulamin ] [ Kontakt ] [ Reklama ]   © wkuwanko.pl 2008-2019 właściciel serwisu SZLIFF

Partnerzy: matzoo.pl matmag.pl batmat.pl pisupisu.pl Matematyka