główne okno aplikacji
Transkrypt
główne okno aplikacji
PROE – wykład 4 dr inż. Jacek Naruniec Zmienne automatyczne i dynamiczne Zmienne automatyczne: dotyczą kontekstu, po jego opuszczeniu są usuwane, powinny być używane wszędzie gdzie jest taka możliwość - w miejsce zmiennych dynamicznych Zmienne dynamiczne Są tworzone podczas wywołania new i usuwane poprzez delete, nie są związane z lokalnym kontekstem, Używamy ich kiedy nie da się w tym miejscu użyć zmiennej automatycznej Zmienne automatyczne i dynamiczne Zaleta zmiennych dynamicznych – mogą być tworzone w dowolnym momencie działania programu i wskaźniki mogą kierować do tablic o długości określonej w trakcie działania programu: Zmienne automatyczne i dynamiczne Przykład 1 (edytor etykiet) pokaz: Zmienna automatyczna, np.: główne okno aplikacji zawiera informację o pozycji okna, składowych itp. , zawsze jedno główne okno aplikacji. Zmienna dynamiczna, np.: otwarte dokumenty (zmienna ilość), zawierają informacje o obiektach wewnątrz, obiekty wewnątrz dokumentu (prostokąty, paski kodów, daty itp.) Zmienne automatyczne i dynamiczne Przykład II (pulsometr): Pomiar czasu Pomiar pulsu Opcjonalnie GPS [pobrane z http://www.runners-world.pl] Zmienne automatyczne i dynamiczne Przy tworzeniu domyślnego obiektu zakładamy, że GPSa nie ma. Jak ma wyglądać destruktor? Czy inne konstruktory też mają przypisywać gps=NULL? Jaka funkcja będzie tworzyć a jaka usuwać GPS? Klasa string W C++ zamiast ciągów znaków char[] zwykle używa się klasy string (include <string>). W przestrzeni nazw std, więc dodajemy using namespace std. Klasa string Najczęstsze formy inicjalizacji: Dodawanie napisów (strcat w char[]): Klasa string Porównywanie napisów (strcmp w char[]): Klasa string Wyszukiwanie napisu w napisie Klasa string Długość napisu: s.length() Ciąg znaków z obiektu klasy string: Wiele innych funkcji … (ask Google) Klasa string Zalety string nad char[] to: Zalety char[] nad string to: Nie martwimy się, że wyjdziemy poza zakres wskaźnika, Mamy jeden obiekt zamiast ciągu znaków, Mamy bezpośrednio dostęp do listy możliwych funkcji klasy, Uproszczone część operacji (np. porównywanie). printf, sprintf, fprintf, scanf, sscanf, fscanf – mnóstwo możliwości odczytu i zapisu z/do konsoli/pliku/ciągu Wybór string/char[] zależy często od aplikacji, ale wskazane jest używanie string. Operacje na plikach Pliki traktujemy tak samo jak strumienie cout, cin. Tworzymy obiekt strumienia plikowego wejściowego (ofstream), wyjściowego (ifstream) lub ogólnego (fstream). Operacje na plikach Operacje na plikach Na stronie prosty przykład z plikiem i okienkiem dialogowym (Windows) Przestrzenie nazw Używane zwykle aby: Uniknąć konfliktu nazw w różnych bibliotekach. Zwiększyć przejrzystość kodu. Przestrzenie nazw Jeśli takie same przestrzenie istnieją w różnych miejscach kodu – łączą się Przestrzenie nazw Przestrzenie nazw Jeśli wpiszemy: Oznacza to, że bez podania nazwy przestrzeni domyślnie korzystamy z PrzestrzenGienka, czyli: Przestrzenie nazw Stąd nasze using namespace std; sprawia, że korzystamy z przestrzeni nazw std domyślnie. Nie musimy wtedy pisać std::cout tylko po prostu cout Tak samo string i std::string i inne… Można mieć włączone wiele domyślnych przestrzeni nazw, ale wtedy nazwy elementów nie mogą się pokrywać, czyli: Forward declaration Co będzie jeśli klasa Punkt będzie korzystała z klasy Wektor a klasa Wektor z klasy Punkt? To nie jest nietypowa sytuacja: Forward declaration Jeśli w mainie zostanie dołączony Wektor.h, w drugiej linijce (po #pragma once) będzie miał: Include „Punkt.h” -> Punkt.h będzie miał po #pragma once #include „Wektor.h” Kompilator nie wejdzie w Wektor.h, bo na początku jest #pragma once które wymusza fakt, że nie dołączymy tego pliku 2 razy. W rezultacie nagłówek ten będzie pominięty, powrócimy do dalszej kompilacji Punkt.h Punkt.h w przesunOWektor korzysta z klasy Wektor która jeszcze nigdzie nie została zadeklarowana i zgłasza błąd. Forward declaration #include „Wektor.h” (w bloczkach kolejność w której będzie zaglądał do plików kompilator) 3 1 4 2 6 7 8 – błąd, bo nigdy nie doszliśmy do definicji Wektor 5 – dalej nie pójdzie, bo pragma once! Forward declaration Zamiast dołączać Wektor.h i Punkt.h powiemy tylko kompilatorowi, że będzie coś takiego jak Punkt i jak Wektor (bez żadnych szczegółów): Teraz działa jak należy… Forward declaration Dziedziczenie Jedna z najważniejszych cech programowania obiektowego! Jest to uszczegółowienie klasy. Uszczegóławiając klasę dodajemy jedynie te elementy, które pojawiają się w nowym obiekcie. Dziedziczenie Klasa OknoProgramu (różnice także w uruchomieniu – albo nieblokujące albo blokujące) Okno programu Okno dialogowe Okno edycyjne Rozszerzone okno dialogowe Okno hasła Dziedziczenie Okno dialogowe nie jest częścią okna programu – jest jego uszczegółowieniem Podobnie okno hasła nie jest częścią okna edycyjnego Itd… Dziedziczenie Okno programu stanowi „bazę” dla pozostałych okien (w rzeczywistości będzie zawierać więcej funkcji) – jego ogólny wygląd ustala system. Te metody będą dotyczyły każdego okna To są zmienne, które definiują okno każdego typu (także dialogowe, hasła, edycyjne) Dziedziczenie Okno dialogowe rozszerza działanie okna o przyciski (powinna być jeszcze zawartość itp.): To znaczy, że dziedziczy po klasie OknoProgramu Identyczna funkcja jak w OknoProgramu Dziedziczenie Rozszerzone okno dialogowe rozszerza okno dialogowe o możliwość ustawienia koloru tła. Nie ma funkcji pokazOkno() ! Dziedziczenie Okno edycyjne rozszerza działanie OknaProgramu o pole edycyjne (ale nie zawiera żadnych przycisków) Dziedziczenie OknoHasla jest uszczegółowieniem okna edycyjnego – kropki zamiast liter i dodatkowy przycisk OK. Kod aby hasło nie występowało jawnie w pamięci. Dziedziczenie Klasa Detektor Detektor Detektor ruchu Detektor twarzy Detektor twarzy Haar Detektor twarzy LBP Dziedziczenie Obiekt Detektor (bardzo ogólny) ? Dziedziczenie Detektor ruchu dziedziczy po detektorze i daje wyniki w postaci maski pikseli które się poruszyły obraz maska ruchu Dziedziczenie Detektor twarzy dziedziczy po detektorze i daje wyniki w postaci tablicy obiektów typu Twarz. Nie implementuje żadnej konkretnej metody, jest ciągle ogólny, ale wiemy jaki wynik chcemy otrzymać. wykryte twarze obraz Dziedziczenie DetektorTwarzyHaar rozszerza działanie detektora twarzy, implementując konkretną metodę detekcji (transformata Haara) Dziedziczenie DetektorTwarzyLBP rozszerza działanie detektora twarzy, implementując konkretną metodę detekcji (cechy Local Binary Patterns - LBP) Dziedziczenie Implementacja klasy Detektor: Dziedziczenie Najprostsze wykorzystanie obiektu bazowego (0 filozofii): Po co nam taki obiekt?? – przecież on w zasadzie nic nie robi i nie ma żadnej sensownej funkcjonalności. My przecież chcemy mieć narzędzie do detekcji Dziedziczenie Implementacja klasy DetektorTwarzy, zaczniemy od konstruktora: Te zmienne dotyczą wszystkich detektorów więc chcemy też z nich korzystać! Rozwiązaniem jest trzeci tryb bloków (przy private i public) – tryb chroniony, czyli protected Dziedziczenie Sekcja protected oznacza, że z metod i zmiennych mogą korzystać klasy pochodne, ale nie można korzystać z nich tutaj nie ma problemu z zewnątrz: Tu zgodnie z założeniem nie można tego zrobić Dziedziczenie Od tego momentu wszystkie składowe (czyli większość jak nie wszystko) które chcemy aby były dziedziczone umiejscawiamy w sekcji protected. Tu w sumie zbędne (bo dalej nie ma dziedziczenia), ale nie zaszkodzi