EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi

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

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

TEMAT : KLASY DZIEDZICZENIE

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

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

PARADYGMATY PROGRAMOWANIA Wykład 4

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

Programowanie Obiektowe i C++

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

Wykład 5: Klasy cz. 3

Dziedziczenie jednobazowe, poliformizm

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

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

Imię i nazwisko: PYTANIA I ODPOWIEDZI Nr 0 EGZAMIN Język C++ 27 czerwca 2011

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

Wykład 8: klasy cz. 4

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Słowa kluczowe i nazwy

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

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

Programowanie Obiektowo Zorientowane w języku C++ Klasy, pola, metody

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

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

Programowanie obiektowe, wykład nr 6. Klasy i obiekty

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Lab 9 Podstawy Programowania

Szablony klas, zastosowanie szablonów w programach

Podstawy Programowania Obiektowego

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

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

Programowanie obiektowe w C++ Wykład 12

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

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

C++ Przeładowanie operatorów i wzorce w klasach

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Identyfikacje typu na etapie. wykonania (RTTI)

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

PARADYGMATY PROGRAMOWANIA Wykład 3

Techniki Programowania wskaźniki

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Język C++ Różnice między C a C++

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Programowanie w C++ Wykład 13. Katarzyna Grzelak. 4 czerwca K.Grzelak (Wykład 13) Programowanie w C++ 1 / 26

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Język C++ wykład VIII

Programowanie, część I

Nowe słowa kluczowe. Komentarze. Wskaźniki typu void. class, delete, new, friend,... /* Komentarz w C i C++ */ // Komentarz w C++ (do końca wiersza)

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

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy PRAWA PRZYJACIÓŁ KLASY. Dostęp z zewnątrz: Dostęp z wewnątrz:

Podstawy Programowania Obiektowego

Język C++ Programowanie obiektowe

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

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

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

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

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

Programowanie obiektowe, wykład nr 7. Przegląd typów strukturalnych - klasy i obiekty - c.d.

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

Dziedziczenie. Ogólna postać dziedziczenia klas:

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

Operatory na rzecz typu TString

Wstęp do programowania obiektowego, wykład 7

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

Informatyka II Laboratorium 3 : Programowania obiektowe C++ - dziedziczenie

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

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

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

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

Zmienne, stałe i operatory

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

C++ - [4-7] Polimorfizm

W dowolnym momencie można zmienić typ wskaźnika.

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

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

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

Zaawansowane programowanie w języku C++ Przeciążanie operatorów

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

Programowanie obiektowe w języku C++ Zarządzanie procesami. dr inż. Jarosław Forenc. Przeładowanie (przeciążanie) operatorów

PARADYGMATY PROGRAMOWANIA Wykład 2

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

Programowanie obiektowe

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

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

Instrukcja do pracowni specjalistycznej z przedmiotu. Obiektowe programowanie aplikacji

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

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

Programowanie obiektowe

Przeciążenie operatorów

Programowanie obiektowe i C++ dla matematyków

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

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy:

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Stos liczb całkowitych

dr inż. Jarosław Forenc

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 12

Wykład 5 Okna MDI i SDI, dziedziczenie

Transkrypt:

EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi 1. Napisz wskaźnik do funkcji fun tak zdeklarowanej: T* fun( int, double const& ) const; definicja wskaźnika musi być precyzyjna, inaczej nie byłby to wskaźnik do tej funkcji T* (*ptr)(int, double const&) const; 2. Oto definicja klasy, oraz kawałek kodu w programie. Dopisz w miejsce kropek to, czego w tej klasie brakuje. class MojaKlasa { public: MojaKlasa( const MojaKlasa& ); virtual ~MojaKlasa(); MojaKlasa(); // gdzieś w programie MojaKlasa tablica[10]; Tablica wymaga konstruktora domyślnego, ponieważ zdefiniowano już konstruktor kopiujący, nie będzie wygenerowany konstruktor zwykły i trzeba go napisać samemu. 3. Napisz deklarację zmiennej o nazwie liczba, typu całkowitego bezznakowego: extern unsigned liczba; // może też być: extern unsigned int liczba; Zwracam uwagę, że pytano o deklarację, a nie definicję (definicja jest też deklaracją, ale jednak należało precyzyjnie udzielić odpowiedzi na pytanie). 4. Napisz słowny opis do następujących definicji: double ( *alfa[4] ) ( int*& ); Na przykład tak: alfa to 4 elementowa tablica wskaźników do funkcji, przyjmującej jako argument wskaźnik do int przez referencję, a zwracającej double. Czasami w odpowiedzi pisano o jakimś wskaźniku do referencji, coś takiego nie istnieje! 5. Wymień operatory, które przy przeciążaniu muszą być metodami składowymi klasy: = () [] > 6. Co się stanie, jeśli nie powiedzie się takie rzutowanie: dynamic_cast< T& > ( x ); Zostanie zgłoszony wyjątek (typu bad_cast) 7. Mamy takie wskaźniki: double const * ptr1; double * const ptr2; Napisz jak należy wykonać operację rzutowania (operatorem z języka C++) tak, żeby można było przypisać ptr1 = ptr2 : Operację tą należy wykonać tak: ptr1 = const_cast< double const* > ( ptr2 ); 8. Ile razy w wywołaniu funkcji fun będą wywoływane jakiekolwiek konstruktory klasy T? Definicja funkcji: T fun( const T arg ) try { T t(); throw T(); catch( T ) { return T(); 4 razy. Najpierw argument przekazany przez wartość (cc tor), potem utworzenie obiektu przy zgłoszeniu wyjątku (c tor), potem przechwycenie wyjątku ale przez wartość czyli robiona kopia (cc tor) i wreszcie w instrukcji return też zrobienie obiektu (c tor). Może warto skomentować, że T t(); to jest tylko deklaracja bezargumentowej funkcji o nazwie t, zwracającej przez wartość typ T (a więc żaden obiekt nie jest tu tworzony).

9. W poniższym kodzie są cztery błędy (punkt przyznany tylko za poprawne zaznaczenie wszystkich). Zaznacz wyraźnie poprawki na kodzie: struct Klasa { enum Funkcja = (znak = nieprawidłowy) { euczen, eprzewodniczacy, Skarbnik ; (brak średnika) Klasa( Funkcja* o ) : osoba ( *o ) { // alternatywnie, np.: Klasa(Funkcja& o) albo przez wartość private: Funkcja osoba; ; (brak średnika) 10. Co się dzieje jeśli po zgłoszeniu wyjątku, podczas usuwania lokalnych obiektów, destruktor jednego z nich też zgłosi wyjątek (krótko opisz sytuację domyślną). wywołana jest funkcja terminate(), która z kolei wywołuje funkcję abort() 11. Mamy klasę, a w niej pewną deklarację przyjaźni (jest to tylko fragment kodu) class Klasa { friend void fun( unsigned ) { Napisz w kodzie programu jak byś mógł wywołać taką funkcję: int main() { // tu kawałek twojego kodu fun( 5 ); // lub cokolwiek podobnego fun w każdym razie nie jest metodą składową klasy! 12. Dla obiektów klasy T napisz deklarację przyrostkowego operatora inkrementacji w postaci funkcji globalnej: const T operator++(t&, int); // ewentualnie bez const, ale zwracanie nie przez referencję! Tyle wystarczyło, bo pytano o deklarację, można było dodać coś na temat przyjaźni choć to już zależy przecież od szczegółów definicji klasy T, których tutaj nie znamy. 13. Mamy dwie klasy, bazową A i pochodną B. Co trzeba wpisać w klasie B w miejsce kropek, żeby poniższy program się kompilował? class A { public: int a; class B : A { public: // zauważmy, że A jest dziedziczone prywatnie! using A::a; // ewentualnie samo: A::a; zachowujemy publiczny dostęp mimo prywatnego dziedziczenia int main() { int A::*ptr = &B::a; Wskaźnikowi do składowej ptr przypisano potem obiekt z klasy pochodnej, ale ten odziedziczony. Nie może więc być rozwiązaniem np. ponowna definicja zmiennej a w klasie B, bo wtedy taki wskaźnik, który nic kompletnie nie wie o klasie B (ponad to, co ona odziedziczyła) nie mógłby być ustawiony na a. 14. Ilu argumentowy jest przeciążony operator > oraz co musi zwracać? Operator przeciążany jest jednoargumentowy i musi (ostatecznie) zwracać wskaźnik, tzn. może zwracać obiekt z kolejnym przeciążonym operator > ale na końcu musi być zwracany wskaźnik. 15. Jakie dwie operacje wykonuje operator new podczas swojego działania? 1) zdobycie pamięci (co się oczywiście wiąże z pozyskaniem/zwróceniem adresu do niej) 2) wywołanie konstruktora obiektu Na tą drugą operację nie mamy wpływu (zawsze jest wykonywana przy wywołaniu new), pierwszą można modyfikować podczas przeciążania operatora.

16. Napisz (dokończ) poprawnie definicję konstruktora klasy C, jeśli klasy bazowe A i B wyglądają następująco: class A { public: A(int) { class B : public virtual A { public: B(char) : A(7) { class C : B { public: // na przykład: C() : A(7), B( a ) { Klasa A jest dziedziczona wirtualnie, więc za jej konstrukcję odpowiada typ najbardziej pochodny. Ponieważ klasa A nie ma konstruktora domyślnego, więc trzeba go jawnie zapisać na liście inicjatorów konstruktora klasy C, podając jakiś parametr (właściwego typu). 17. Mamy klasę bazową A oraz zdefiniowany w niej operator= następnie klasę pochodną B. W definicji operatora = z klasy B zapisz w dowolny sposób linię dotyczącą wywołania operatora z klasy bazowej oraz ostatnią linię: class A { public: A& operator=( const A& src ); class B : public A { public: B& operator=( const B& src ) { // jakiś kod sposób zapisu jest kilka do wyboru, np. A::operator=( src ); // tu wywołaj operator= z klasy bazowej w dowolny sposób // jakiś kod na koniec trzeba oczywiście zwrócić sam obiekt (nie wskaźnik!) return *this; // tu napisz co musi być na końcu 18. Wskaż wśród poniższych fałszywą odpowiedź: a. funkcja globalna: static void fun() { b. funkcja globalna: void fun() const { c. funkcja składowa klasy T: void T::fun() const volatile { d. funkcja składowa struktury T: struct T { static void fun() { Odpowiedź b. jest niepoprawna, ponieważ funkcja globalna nie może mieć modyfikatora cv (const / volatile). Reszta odpowiedzi jest poprawna! 19. Dla klasy A napisz operator konwersji do typu std::string class A { const char* ptr; public: operator std::string() { return ptr; Można oczywiście (po uprzednim zadeklarowaniu użycia) opuścić std::, można też inaczej zapisać zawartość, np. tworząc obiekt typu string w środku, ale tak jak wyżej podano, jest najkrócej i najprościej. 20. Co to jest this? jakiego jest typu np. dla klasy T, gdzie jest przekazywane i czemu służy? 1) this jest wskaźnikiem i jest on typu T * const (czyli stały wskaźnik) 2) przekazywany niejawnie wszystkim niestatycznym metodom składowym klasy można w związku z tym zauważyć, że jeśli metoda jest const i/lub volatile, to takiż przydomek nabywa również ten wskaźnik, czyli np. dla metody stałej będzie on typu const T * const 3) zawiera adres konkretnej instancji (obiektu), dzięki niemu metody wiedzą na jakim egzemplarzu danych pracują (każdy obiekt ma swoje dane)

21. Dla klasy A napisz (dokończ) konstruktor, który będzie chroniony tak zwanym try funkcyjnym (razem z dowolną procedurą obsłużenia zgłoszonego wyjątku). Ponadto odpowiedz na pytanie, czym kończy się obsłużenie wyjątku zgłoszonego wewnątrz takiego try? class A { public: // można to było dowolnie to napisać, ale składniowo poprawnie w sensie właściwych nawiasów, np.: A() try : (tu coś na liście inicjatorów) { tu zasadnicza treść catch( ) { tu blok obsługi wyjątku try funkcyjny wraz z blokiem obsługi wyjątku zawsze kończy się ponownym zgłoszeniem wyjątku (czyli tak jak gdyby na końcu bloku catch napisać throw; lub zgłosić inny wyjątek) 22. W klasie A zadeklarowana jest metoda czysto wirtualna, która potem jest też zdefiniowana: class A { public: virtual void fun() = 0; void A::fun() { // definicja Wybierz z poniższych fałszywe stwierdzenie: a. metodę fun() można wywołać w konstruktorze klasy A b. metodę fun() można wywołać w destruktorze klasy A c. metodę fun() w klasie dziedziczącej z klasy A nie trzeba już definiować, bo została zdefiniowana d. można na nią ustawić wskaźnik na metodę składową: void (A::*p)() = &A::fun; 23. Jeśli mamy klasę A: class A { public: virtual Foo* fun(); to jakie kryteria musi spełniać typ Bar w klasie pochodnej: class B : public A { public: Bar* fun(); żeby dla wyołania (new B) >fun(); działał polimorfizm? żeby możliwe było w ogóle napisanie wirtualnej funkcji fun() o takich samych parametrach, oraz żeby działał polimorfizm, typ Bar musi być typem pochodnym od typu Foo. Nie rozumiem tego, jeśli ktoś pisał, że Bar musi być taki sam albo tego samego typu co Foo. Oczywiście tak można potocznie powiedzieć, ale nie wyczerpuje to istoty sprawy. 24. Mamy klasę: class A { public: A() { cout << OK ; A( const A& ) { cout << OK ; ~A() { cout << OK ; Ile razy zobaczymy na ekranie OK w wyniku działania poniższego kodu: int main() { A *ptr = new A; A obj = *(new A); 4 razy. W pierwszej linii tylko konstruktor, w drugiej konstruktor, po czym konstruktor kopiujący (bo jest tworzony obiekt obj), na koniec destruktor obiektu obj. Zasoby pokazywane przez wskaźnik ptr nie są usuwane (brak linijki delete ptr) tym samym nie ma destruktora tych zasobów. 25. Które z poniższych porównań typów, wykorzystujące RTTI, zwraca wartość true? a. typeid( short ) == typeid( 3 ) b. typeid( float ) == typeid( 3.14 ) c. typeid( float*const ) == typeid( new float ) d. typeid( float const* ) == typeid( *(new double) )

Liczba 3 sama w sobie oznacza typ int, liczba 3.14 sama w sobie oznacza typ double (było to na wykładzie dyskutowane przy okazji stałych dosłownych języka). Natomiast w przypadku wskaźnika float * const przydomek const nie dotyczy wskazywanego typu, tylko określa charakter wskaźnika ( że jest on stały). Wskazywany typ to float* co zgadza się z prawą stroną (new float). 26. Dla klasy A: class A { public: int a; napisz definicję operatora operator<< tak, żeby możliwe było w programie: A obj; cout << obj; Taki operator nie musi być przyjacielem, bo klasa A ma jeden składnik publicznie dostępny. ostream& operator<<( ostream& stream, const A & src ) { return stream << src.a; // gdy ktoś deklarował przyjaźń, to mimo powyższego akceptowałem to : ) 27. Klasę A uzupełnij tak, żeby możliwe było w programie przypisanie: A obj = 77; class A { int a; // na przykład: A(int n) : n( a ) { Linijka z programu: A obj = 77; nie oznacza w żadnym wypadku operacji przypisania! Ponieważ obj jest właśnie tworzony, działa tu konstruktor kopiujący. Ponieważ jednak argument tego konstruktora nie pasuje typem (bo jest to liczba 77, czyli int), musi nastąpić jakaś konwersja. Jest ona możliwa gdy dostarczymy konstruktor konwersji o jednym argumencie typu int. 28. Napisz wskaźnik, jaki powinien być po lewej stronie poniższej operacji: int zmienna = 3; int (*ptr)[4] = new int[zmienna][4]; 29. W pewny zakresie utworzono kilka obiektów. Wszystkie powinny zostać usunięte, napisz konieczne instrukcje to wykonujące: { double *p1 = new double(3); auto_ptr<char> p2( new char ); short *p3 = new short[5]; // teraz usuwanie, napisz co trzeba delete p1; // bo utworzono jeden obiekt do wskaźnika p1 delete [] p3; // bo utworzono tablicę obiektów do wskaźnika p3 p2 oczywiście nie usuwamy, bo obiekt auto_ptr jest właśnie obiektem na stosie, sam się usunie 30. Podaj wynik następującej operacji (pytanie z haczykiem ): 2 ^ 1!0 To było jedyne pytanie, na które całkiem poprawna odpowiedź wymagała dużej erudycji i zupełnie przypadkiem spora część z Państwa, mimo podążenia złym tokiem rozwiązania, dostała poprawny wynik. Rezultat tego obliczenia to 2. Natomiast poprawna do niego droga jest następująca: operator ^ to nie jest oczywiście żadne podnoszenie do potęgi, bo takiego operatora w c++ nie ma, ten operator oznacza w tym języku różnicę bitową ( bitwise exclusive or ). Trzeba więc umieć sobie przedstawić liczbę 1 oraz 2 w postaci binarnej, np. 0001 oraz 0010. Różnica bitowa na tych liczbach daje 0011, czyli 3. A jednak nie tak się to liczy w tym przypadku! Dlaczego? Ponieważ operator odejmowania ( ) ma wyższy priorytet niż operator ^. Jeszcze wyższy priorytet ma negacja logiczna, czyli operator!. A zatem, kolejno mamy:!0 sprawia, że 0 jest konwertowane na false, następnie zamieniane operatorem! na true. Wartości logicznej true odpowiada 1 (a nie dowolna liczba to jest w drugą stronę konwersji ) i ponieważ dalej mamy do czynienia z odejmowaniem 1!0 to true jest zamieniane właśnie na 1: zatem 1 1 daje 0. Ostatnia operacja: 2^0 daje 2.