IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi EGZAMIN PIERWSZY (25 CZERWCA 2013) JĘZYK C++ poprawiam ocenę pozytywną z egzaminu 0 (zakreśl poniżej x) 1. Wśród poniższych wskaż poprawną formę definicji programu w C++ a) main( ) -> int { } b) auto [] () -> int { } c) auto main( ) { } d) auto main( ) -> int { } // tylko to jest poprawne e) void main( ) { return 0; } 2. Po wykonaniu fragmentu poniższego kodu, jaka będzie wartość pierwszego elementu w tablicy tab: int tab[] { 1, 2, 3, 4 for (auto i : tab) i = i+1; Taka sama jak po inicjalizacji, czyli 1 (pętla for pobiera wartość kopię, więc niczego nie zmienia). 3. Zakładając, że jesteśmy w przestrzeni globalnej, które z poniższych nie jest deklaracją (tzn. jest też być może również definicją): a) enum struct Ksztalt; b) static long n; // definicja c) extern double d = 0; // definicja, bo inicjalizacja d) namespace { } // definicja nienazwanej przestrzeni nazw e) class Foo; f) extern const int i; 4. Wymień dwa sposoby, na jakie można ograniczyć zasięg (widzialność) danej nazwy do pojedynczej jednostki translacji. 1) poprzez static (w przestrzeni globalnej) 2) poprzez zamknięcie w nienazwanej przestrzeni nazw 5. Co się stanie w efekcie kompilacji / wykonania poniższego kodu? void fun(int){ cout << "1" << endl; } void fun(int*){ cout << "2" << endl; } void fun(int*&){ cout << "3" << endl; } void fun(int**){ cout << "4" << endl; } int main( ) { fun(nullptr); } Błąd kompilacji z powodu niejednoznaczności wywołania przeciążonych wersji funkcji (2 i 4). 6. Proszę podać jakiego typu jest zmienna a oraz jakiego typu jest zmienna b: auto a = * new auto ( 0 ); // typu int decltype( new auto ( 0 ) ) b; // typu int* 1
7. Jaka jest wartość zmiennej a po takich operacjach: int a = 4; a ^= a; Wartość końcowa a wynosi 0 (gdyż ^ to XOR a na samym sobie daje zero, ^= to XOR z przypisaniem). 8. Uzupełnij miejsca... w dowolny poprawny sposób: class Bar : public Foo { // w programie: Bar b; auto p = dynamic_cast< Foo& > ( b ) ; // zamiast auto można jawnie napisać Foo& 9. Jak należy zapisać argument funkcji tak, żeby dopuszczalna była tylko 5-elementowa tablica char void fun( char (&tab) [5] ); // nazwa tab nie jest konieczna w deklaracji 10. Które z poniższych deklaracji funkcji globalnych są niepoprawne: a) void fun( int, char = 'a', void* = 0 ); b) void fun( int* p = nullptr, int ); // niepoprawne c) void fun( int a, int b, int = 4 ); d) void fun( void ) const; // niepoprawne, bo w przestrzeni globalnej nie ma funkcji const e) void fun( auto n = 5 ); // niepoprawne 11. Jaką wartość będzie miała składowa i po utworzeniu obiektu w programie (jak poniżej): int i = 10; Foo( int i ) : i ( i ) { } // w programie Foo i(5); a) 5 // tą wartość b) 10 c) niezdefiniowaną bo nie wiadomo które i jest wartością inicjalizującą d) program się nie skompiluje e) 0 12. Zdefiniowano konstruktor w części prywatnej klasy. Jak wykorzystać go do definicji innych konstruktorów: Foo ( int, int, double ); // na przykład: Foo( ) : Foo ( 0, 0, 0.0 ) { } Foo( int a ) : Foo ( a, a, 0.0 ) { } 2
13. W poniższej klasie zdefiniuj niejawny operator konwersji do typu std::string const char * ptr; explicit operator string( ) { return ptr; } 14. Wśród poniższych wskaż wszystkie fałszywe twierdzenia: a) jeśli zdefiniuję konstruktor kopiujący, to nie wygeneruje się automatycznie konstruktor przenoszący b) jeśli zdefiniuję konstruktor kopiujący, to nie wygeneruje się automatyczny konstruktor domyślny c) jeśli zdefiniuję destruktor, to nie wygeneruje się automatyczny konstruktor kopiujący d) jeśli zdefiniuję konstruktor konwersji, to nie wygeneruje się domyślny konstruktor e) jeśli zdefiniuję konstruktor konwersji, to nie wygeneruje się automatyczny konstruktor kopiujący // fałszywe jest e, bo wygeneruje się 15. Dla dowolnego typu T napisz deklarację globalnego operatora przedrostkowego i przyrostkowego inkrementacji. przedrostkowy: const T& operator++ ( T& ); przyrostkowy: const T operator++( T&, int ); 16. Proszę zdefiniować wskaźnik na składową int poniższej klasy Foo i ustawić na składową a int a; int Foo::*ptr = &Foo::a; 17. Wskaż wśród poniższych wszystkie fałszywe twierdzenia: a) operator [] jest operatorem tylko o jednym argumencie b) operator wyłuskania * musi być metodą składową klasy // fałsz c) operator odniesienia się na składową -> musi być metodą składową klasy d) nie można przeciążyć operatora ->* // fałsz e) operator przecinkowy, można przeciążyć tylko w postaci funkcji globalnej // fałsz 18. W jakiej kolejności uruchamiane będą konstruktory klas w poniższym kodzie (definicje pomijami dla czytelności, konstruktory są domyślne): class A; class B : virtual A; static A a; int main( ) { B b; A *ptr; } Kolejno: A A B (proszę zwrócić uwagę, że A *ptr; niczego nie uruchamia to tylko wskaźnik). 3
19. Co zostanie wypisane na ekran: struct Foo { virtual Foo* fun() { cout << "F" << endl; return this; } struct Bar : public Foo { Bar* fun() { cout << "B" << endl; return this; } int main( ) { Foo* ptr = new Bar; ptr->fun(); // B (*ptr).fun(); // B } 20. Napisz jak utworzyć: 20-elementową tablicę typu char na stercie char *p = new char[20]; 20-elementową tablicę typu void* na stosie void* tab[20]; 21. Zaznacz (kółkiem lub dopisz jeśli czegoś brak) virtual void fun( ) = 0; explicit Foo( int ); virtual ~Foo ( int=0 ); // d-tor nie może mieć argumentu } ; // brak średnika 22. Jest funkcja w postaci: void fun( initializer_list<int> n ); W jaki sposób należy wywołać taką funkcję, napisz jakiś przykład: fun ( { 1, 2, 3 } ); 23. Co się stanie w poniższym kodzie? explicit Foo(int) {} class Bar : public Foo { using Foo::Foo; int main( ) { Bar b = 7; } Błąd kompilacji ze wzgl. na to że konstruktor Foo jest explicit i taka własność jest odziedziczona. 24. Napisz przykład definicji i inicjalizacji kontenera vector dla typu double. Następnie pętlę "po cały zakresie" (wg nowej składni) wypisującą kolejne elementy na ekran. vector<double> v { 0., 1.5, 2.8 for (auto d : v ) cout << d << endl; 25. Jeśli utworzyliśmy dopiero co kontener map< string, int > to co spowoduje taki zapis: map["alfa"]; Tak zapis spowoduje utworzenie pary i wstawienie jej do mapy (klucz alfa wartość 0). 4
26. Napisz dla klasy Foo takie deklaracje, które zablokują operacje kopiowania (proszę użyć składni w tym pomagającej z języka C++11) Foo( const Foo& ) = delete; // blokada konstruktora kopiującego Foo& operator= (const Foo& ) = delete; // blokada operatora= kopiującego 27. Mamy klasę Lambda z przeciążonym operatorem funkcyjnym, napisz dla niej jak wyglądałoby ekwiwalentne jej wyrażenie Lambda: class Lambda { T& t; Lambda( T& t1 ) : t( t1 ) {} void operator( )( ) { fun( t ); } [ &t ]() { fun(t); } 28. Napisz deklarację przyjaźni dla operatora >> wyjmowania ze strumienia, dla poniższej klasy friend std::istream& operator>>( std::istream& s, Foo& f ); 29. Zdefiniuj i zainicjalizuj dowolną poprawną wartością a static char a; char Foo::a = 0; // w sumie 0 to domyślna wartość inicjalizacji pola statycznego 30. Klasa Bar dziedziczy prywatnie z klasy Foo. W klasie Foo w części publicznej jest metoda void fun() const; Co należy napisać i w której części klasy Bar, żeby ta metoda nadal była publiczna. W części publicznej klasy Bar należy napisać: using Foo::fun; 31. Dla klasy Foo przeciąż operator new (wystarczy napisanie odpowiedniej deklaracji). void* operator new (size_t s); 32. Wymień wszystkie operatory, które można przeciążyć i muszą być składowymi klasy. operator= operator() operator[] operator-> 5
33. Funkcja fun przyjmuje argument przez referencję i zwraca przez referencję. Napisz poprawną instrukcję zwrotu wewnątrz funkcji, zwracającą to co weszło do niej przez argument int& fun( int& n ) { return n; 34. Czym w języku c++ różni się klasa od struktury (pod względem pól dostępu, dziedziczenia)? Różni się tym, że domyślnym polem dostępu w klasie jest private, a w sktrukturze public. Podobnie domyślnym sposobem dziedziczenia w klasie jest private, a w strukturze public. Domyślnym, tzn. takim jakie jest gdy się go nie napisze jawnie. 35. Napisz jak wygląda deklaracja main jeżeli chcemy przyjąć jakieś argumenty podczas wywołania programu. // oba zapisy są tożsame int main( int argc, char** argt ); int main( int argc, char* argt[] ); 6