Identyfikacje typu na etapie. wykonania (RTTI)

Podobne dokumenty
Obsługa wyjątków. Język C++ WW12

Składnia C++ Programowanie Obiektowe, część 3 Mateusz Cicheński

Zaawansowane programowanie w języku C++ Programowanie obiektowe

PARADYGMATY PROGRAMOWANIA Wykład 4

EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi

EGZAMIN 2 (14 WRZEŚNIA 2015) JĘZYK C++

Wykład V. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Szablony. Szablony funkcji

Szablony funkcji i szablony klas

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Owad():waga(1),jadowitosc(false) {cout<<"konstruktor domyslny owada\n";}

C++ - [4-7] Polimorfizm

Wprowadzenie do szablonów klas

Abstrakcyjny typ danych

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class).

Rzutowanie i konwersje

Funkcje wirtualne. Wskaźniki do klas pochodnych są podstawą dla funkcji wirtualnych i polimorfizmu dynamicznego.

Programowanie obiektowe w języku

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

ATD. Wykład 8. Programowanie (język C++) abstrakcyjny typ danych. Abstrakcyjne typy danych (ATD) Metody czysto wirtualne. Definicje i uwagi:

Plik klasy. h deklaracje klas

class Samochod { void Ruch(); }; class Amfibia : public Samochod { void Ruch(); // amfibie pływają };

TEMAT : KLASY DZIEDZICZENIE

Wprowadzenie do szablonów szablony funkcji

Wprowadzenie do programowanie obiektowego w języku C++

Wprowadzenie do szablonów szablony funkcji

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Programowanie obiektowe w C++ Wykład 12

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Programowanie komputerowe. Zajęcia 4

Dziedziczenie. Ogólna postać dziedziczenia klas:

Ściąga z JTP. (Ja Tjeba Pierd...) Uwagi, nowe pytania, poprawki itd. zgłaszać na forum mambo.

C++ język nie dla ludzi o słabych nerwach. Małgorzata Bieńkowska

Zaawansowane programowanie w C++ (PCP)

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Wyjątki. Wyjątki. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Politechnika Wrocławska

Programowanie 2. Język C++. Wykład 3.

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Technologie cyfrowe semestr letni 2018/2019

Instrukcja do pracowni specjalistycznej z przedmiotu. Obiektowe programowanie aplikacji

Programowanie Komputerów

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Techniki Programowania wskaźniki

Język C++ wykład VII. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VII. dr Jarosław Mederski. Spis.

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Programowanie Obiektowew języku C++ Zadania L4

Technologie cyfrowe semestr letni 2018/2019

Szablony klas, zastosowanie szablonów w programach

C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie C++ - DZIEDZICZENIE.

string Rodzaj[4]= {"TV ", "wieza ", "DVD ", "kino "}; string Producent[4]={"Phillips", "Sony ", "Sanyo ", "Samsung "};

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Programowanie obiektowe. Wykład 5. C++: szablony

Klasa dziedzicząca posiada wszystkie cechy klasy bazowej (plus swoje własne) dodawanie nowego kodu bez edycji (i ewentualnego wprowadzania

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 4. Karol Tarnowski A-1 p.

Na ekranie monitora zostaną wyświetlone w dwu liniach teksty Pierwsza linia Druga linia

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Programowanie 2. Język C++. Wykład 9.

Algorytmy i Struktury Danych. Anna Paszyńska

Programowanie obiektowe i zdarzeniowe

Środowisko programistyczne GEANT4

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Języki i techniki programowania Ćwiczenia 2

Wyjątki (exceptions)

DYNAMICZNE PRZYDZIELANIE PAMIECI

Zaawansowane programowanie w C++ (PCP)

Słowa kluczowe i nazwy

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

Język C++ wykład VI. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VI. dr Jarosław Mederski.

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Przeciążenie operatorów

Wstęp do programowania obiektowego, wykład 7

Operacje wejścia/wyjścia (odsłona druga) - pliki

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

it = 0; memset((void *)ptr, 0, items*sizeof(double)); cout << "Konstruktor sparametryzowany " << title << " adres: " << ptr << "\n";

Programowanie, część I

TEMAT : KLASY POLIMORFIZM

Mechanizm dziedziczenia

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

class Student Deklaracja klasy Osoba: Deklaracja klasy Student:

2.4 Dziedziczenie. 2.4 Dziedziczenie Przykłady programowania w C - kurs podstawowy

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.


Programowanie w języku C++

FUNKCJE WZORCOWE. Wykład 10. Programowanie Obiektowe (język C++) Funkcje wzorcowe wprowadzenie (2) Funkcje wzorcowe wprowadzenie (1)

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

PARADYGMATY PROGRAMOWANIA Wykład 3

C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm POLIMORFIZM

Dziedziczenie jednobazowe, poliformizm

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

Transkrypt:

Identyfikacje typu na etapie (Run Time Type Identification) wykonania (RTTI) Może powstać taka sytuacje, gdy w trakcie kompilacji typ obiektu nie jest znany. C++ implementuje polimorfizm poprzez hierarchie klas, funkcje wirtualne i wskaźniki klas bazowych. Wskaźniki klas bazowych można wykorzystać do wskazywania obiektów klas bazowych, a również, i dowolnych obiektów pochodnych klasy bazowej. Nie wykluczone, że w jakimś miejscu kodu powstanie konieczność wyjaśnić, do obiektu którego typu wskazuje wskaźnik klasy bazowej to się odbywa w trakcie wykonania programu. Operator typeid (dołożyć nagłówek <typeinfo>) : typeid (obiekt) typeid(referencje_do_obiektu) obiekt ten obiekt, typ którego mamy określić (typ wbudowany lub typ, tworzony przez użytkownika) 1

Zwraca referencje typu type_info do argumentu obiekt. W klasie type_info zdefiniowane są następujące składowe publiczne: o bool operator == (const type_info &ob); //służą do porównywania typów o bool operator!= (const type_info &ob); //służą do porównywania typów o bool before(const type_info &ob); //służy do użycia wewnętrz. przy sortow. o const char *name(); //zwraca wskaźnik do nazwy typów class A ; class B ; voidmain() inti; A a; B b; cout << typeid(i).name() << endl; cout << typeid(a).name() << endl; cout << typeid(b).name() << endl; system("pause"); 2

Przykład 2 class A ; class B ; //template <class T, class K> bool funtypcompare(t &x, K &y) //typeid(referencje_do_obiektu) template <class T, class K> bool funtypcompare(t x, K y) cout << typeid(x).name() << " i " << typeid(y).name() << "? \n"; if(typeid(x) == typeid(y)) return true; else return false; void main() int i = 0, j = 0; A a; B b; cout << funtypcompare(a, b) << endl; cout << funtypcompare(i, j) << endl; system("pause"); 3

Przykład 3. Klasy polimorfne. Wskaźnik klasy bazowej może wskazywać obiekt klasy bazowej, a również, klasy pochodnej. Dla wyznaczenia typu obiektu używamy operator wskazania pośredniego *ptr. Jeśli wskaźnik jest zerowy, operator typeid(*ptr) generuje wyjątek bad_typeid class B public: virtual void f() cout << "Jestem B\n"; ; class D1 : public B public: void f() cout << "Jestem D1\n"; ; 4

void main() B b, *pb, *pnull = NULL; D1 d1; pb = &b; pb->f(); cout << "pb wskazuje obiekt typu " << typeid(*pb).name() << endl; pb = &d1; pb->f(); cout << "pb wskazuje obiekt typu " << typeid(*pb).name() << endl; try cout << typeid(*pnull).name() << endl; catch(bad_typeid aa) cout << "bad pointer\n"; system("pause"); 5

Klasy nie polimorfne: kod jest taki samy, jak poprzednio, tylko kluczowe słowo virtual pozostało zakomentowane class B public: ; /*virtual*/ void f() cout << "Jestem B\n"; class D1 : public B public: void f() cout << "Jestem D1\n"; ; 6

void main() B b, *pb, *pnull = NULL; D1 d1; pb = &b; pb->f(); cout << "pb wskazuje obiekt typu " << typeid(*pb).name() << endl; pb = &d1; pb->f(); cout << "pb wskazuje obiekt typu " << typeid(*pb).name() << endl; Jestem B pb wskazuje obiekt typu class B Jestem B pb wskazuje obiekt typu class B Для продолжения нажмите любую клавишу... Dla wskaźników niepolimorficznej hierarchii klas otrzymujemy wskaźnik typu bazowego rzeczywisty typ obiektu wskazywanego nie pozostaje określony. 7

Druga forma operatora typeid: typeid(nazwa_typu) Jest używana dla porównywania typów (czy ma obiekt typ podany?) class B public: ; virtual void f() cout << "Jestem B\n"; class D1 : public B public: void f() cout << "Jestem D1\n"; ; void main() B b, *pb, *pnull = NULL; D1 d1; pb wskazuyje na obiekt typu D1 Для продолжения нажмите любую клавишу... pb = &d1; if(typeid(*pb) == typeid(d1)) cout << "pb wskazuyje na obiekt typu D1\n"; system("pause"); 8

Operator typeid można stosować do szablonów klas: przykład W15_1 Operatory rzutowania dynamic_cast służy do rzutowania wskaźnika na wskaźnik innego typu lub referencji na referencję innego typu w trakcie wykonywania programu i weryfikacji poprawności rzutowania. dynamic_cast <typ_docelowy> (wyrażenie) typ_docelowy typ docelowy rzutowania, wyrażenie wyrażenie, które jest rzutowane na nowy typ. wyrażenie to jest wskaźnik lub referencje, wyrażenie musi być rozwijane do wskaźnika lub referencji. Wynik: powodzenie dynamic_cast zwraca wskaźnik lub referencje poprawnę; niepowodzenie dynamic_cast zwraca NULL, jeśli wyrażenie jest wskaźnikiem, lub generuje wyjątek bad_cast, jeśli wyrażenie jest referencją. Zadaniem dynamic_cast jest przeprowadzenie rzutowania dla typów polimorficznych. 9

Mamy dwie klasy polimorficzne B klasa bazowa, D klasa pochodna. Zawsze można rzutować wskaźnik D * na wskaźnik B * (wskaźnik klasy bazowej zawsze może wskazywać na obiekt klasy pochodnej) Rzutować wskaźnik B * na wskaźnik D * można tylko wtedy, jeśli wskazywany obiekt jest rzeczywiście obiektem klasy D Uogólnienie: wykorzystanie dynamic_cast zakończy się sukcesem, jeśli rzutowany wskaźnik (lub referencje) ma typ docelowy lub wskazuje (referuje) do obiektu klasy pochodnej typu docelowego. W przeciwnym przypadku niepowodzenie. 10

B b, *pb; D1 d1, *pd1; pd1 = &d1; pb = dynamic_cast<b *> (pd1); //OK, wskaznik klasy bazowej zawsze //moze wskazywac na obiekt klasy pochodnej pb = &d1; pd1 = dynamic_cast <D1 *> (pb); //OK, wskaznik klasy bazowej //wskazuje na obiekt klasy pochodnej pb = &b; pd1 = dynamic_cast<d1 *> (pb); //!OK, wskaznik klasy bazowej //nie wskazuje na obiekt typu D1 Przykład W15_0 Operator dynamic_cast<>() może być wykorzystany zamiast operatora typeid(). Przypuszczamy, że mamy polimorficzne klasy B, D (base, derived): B *pb; D *pder; //. if(typeid(*pb) == typeid(d)) //sprawdzamy: wskazuje pb na obiekt klasy pochodnej? pder = (D *)pb; //tak, rzutujemy wskaźnik pb na typ D else pder = NULL; 11

Dokładnie to samo można zrobić w jednej linii kodu: A to bład: pder = dynamic_cast<d *> (pb); pder = (D *)pb; Kompilator nic nie zgłosi, ale jeśli pb nie wskazuje na obiekt klasy D, działanie programu jest nie przewidywane. Takie błędy zwykłe bardzo ciężko wykryć w mnie-więcej rozbudowanym kodzie, dla tego że mogą występować nie za każdym uruchomieniem programu. Przykład W15_2. Jeśli wskaźnik klasy bazowej wskazuje na obiekt klasy pochodnej typu Typ, to wtedy i tylko wtedy rzutowanie p_derived = dynamic_cast<typ *> (p_base) skończy się powodzeniem. Więc warunek if(p_derived = dynamic_cast<typ *> (p_base) ) //tu jest gwarantowane, że wskaźnik p_base wskazuje na obiekt klasy //pochodnej polimorficznej typu Typ else //p_base nie wskazuje na obiekt klasy pochodnej polimorficznej typu Typ 12

Wykorzystanie dynamic_cast do pracy z szablonami klas przykład W15_1. Operator const_cast const_cast<typ> (wyrażenie) o zastępuje podczas rzutowania const i/lub volatile. Typ docelowy musi być takim samym, jako typ źródłowy. Najpopularniejsze użycie usuwanie wpływu atrybutu const. o typ typ docelowy o wyrażenie wyrażenie, rzutowane na nowy typ 13

void fun(const double *ptr) double *p; p = const_cast<double *> (ptr); //usuwamy modyfikator const, inaczej kompilator zgłosi //niespójność typów (double i const double *p += 10.0; *ptr += 10.0; cout << *p << endl; void main() double a[2] = 1.0, 2.0; fun(a); system("pause"); 11 Aby kontynuowac, nacisnij dowolny klawisz... //błąd: error C3892: 'ptr' : you cannot assign to a variable that is //const 14

Operator static_cast<> (): static_cast<typ> (wyrażenie) o Wykonuje rzutowanie niepolimorficzne. Na etapie rzutowania nie są przeprowadzane żadne sprawdzenia. Zastępuje oryginalny operator rzutowania. o typ typ docelowy o wyrażenie wyrażenie, rzutowane na nowy typ int i = 10; double a; a = static_cast<double> (i); // to samo: a = (double)i; Operator reinterpret_cast<> (): reinterpret_cast<typ> (wyrażenie); o służy do konwersji wskazanego typu na typ całkowicie odmienny 15

void main() char *p = "to jest wiersz tekstowy"; int iii = reinterpret_cast<int> (p); cout << iii << endl; system("pause"); Przy kompilacji powstaje ostrzeżenie: warning C4311: 'reinterpret_cast' : pointer truncation from 'char *' to 'int Wynik: 4290308 Для продолжения нажмите любую клавишу... 16