Dzisiejszy wykład. Przestrzenie nazw (namespaces) Funkcje o zmiennej liczbie argumentów



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

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

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

Część 4 życie programu

Podział programu na moduły

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

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

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

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

I - Microsoft Visual Studio C++

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

Projektowanie klas c.d. Projektowanie klas przykład

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

Podstawy programowania skrót z wykładów:

Programowanie obiektowe w C++ Wykład 12

Wstęp do programowania

Przeciążenie (przeładowanie nazw) funkcji

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

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

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

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

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

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

1 Podstawy c++ w pigułce.

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

1 Podstawy c++ w pigułce.

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

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

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

Przekazywanie argumentów wskaźniki

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

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

Co nie powinno być umieszczane w plikach nagłówkowych:

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

C++ wprowadzanie zmiennych

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

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

Wstęp do programowania

Functionalization. Jeszcze o funkcjach i strukturze projektu. Marcin Makowski. 3 grudnia Zak lad Chemii Teoretycznej UJ

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

Przesłanianie nazw, przestrzenie nazw

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

Programowanie obiektowe i C++ dla matematyków

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Pobieranie argumentów wiersza polecenia

PARADYGMATY PROGRAMOWANIA Wykład 4

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

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Wstęp do Programowania, laboratorium 02

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

Abstrakcyjne struktury danych w praktyce

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Funkcje. Spotkanie 5. Tworzenie i używanie funkcji. Przekazywanie argumentów do funkcji. Domyślne wartości argumentów

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

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

2 Przygotował: mgr inż. Maciej Lasota

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

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

C-struktury wykład. Dorota Pylak

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

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

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

Wyjątki (exceptions)

Programowanie komputerowe. Zajęcia 1

Wstęp do Programowania 2

dr inż. Jarosław Forenc

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

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

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

Szablony klas, zastosowanie szablonów w programach

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

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.

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

Operatory na rzecz typu TString

Język C++ wykład VIII

Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1)

Szablony. Szablony funkcji

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

Programowanie - wykład 4

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

Podstawy algorytmiki i programowania - wykład 4 C-struktury

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

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

Zadanie 2: Arytmetyka symboli

Microsoft IT Academy kurs programowania

EGZAMIN PROGRAMOWANIE II (10 czerwca 2010) pytania i odpowiedzi

PARADYGMATY PROGRAMOWANIA Wykład 2

Język ludzki kod maszynowy

TEMAT : KLASY POLIMORFIZM

Języki i paradygmaty programowania Wykład 2. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/18

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

Wprowadzenie. Programowanie Obiektowe Mateusz Cicheński

Wstęp do Programowania 2

Podstawy wykorzystania bibliotek DLL w skryptach oprogramowania InTouch

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

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

Podstawy Programowania Podstawowa składnia języka C++

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

Transkrypt:

Dzisiejszy wykład Przestrzenie nazw (namespaces) Funkcje o zmiennej liczbie argumentów 1

Przestrzenie nazw Globalna przestrzeń nazw jest jedna W programach pisanych przez wiele osób, lub korzystających z bibliotek napisanych przez innych, istnieje ryzyko kolizji nazw // library1.h const double LIB_VERSION = 1.204; // library2.h const int LIB_VERSION = 3; // main.c #include <library1.h> #include <library2.h> Tradycyjnie problem rozwiązuje się przy pomocy prefiksów unikatowych dla każdej biblioteki // library1.h const double library1_lib_version = 1.204; // library2.h const int library2_lib_version = 3; 2

Przestrzenie nazw Zasadniczo przestrzenie nazw zastępują prefiksy identyfikatorów Zamiast const double sdmbook_version = 2.0; class sdmhandle... ; sdmhandle& sdmgethandle(); piszemy: // in this library, // each symbol begins // with "sdm" namespace sdm const double BOOK_VERSION = 2.0; class Handle... ; Handle& gethandle(); 3

Użycie przestrzeni nazw void f1() using namespace sdm; // make all symbols in sdm // available w/o qualification // in this scope cout << BOOK_VERSION; // okay, resolves to sdm::book_version... Handle h = gethandle(); // okay, Handle resolves to // sdm::handle, gethandle... // resolves to sdm::gethandle void f2() using sdm::book_version; // make only BOOK_VERSION // available w/o qualification // in this scope cout << BOOK_VERSION;... Handle h = gethandle(); // okay, resolves to // sdm::book_version // error! neither Handle // nor gethandle were... // imported into this scope void f3() cout << sdm::book_version;// okay, makes BOOK_VERSION // available for this one use... // only double d = BOOK_VERSION; // error! BOOK_VERSION is // not in scope Handle h = gethandle(); // error! neither Handle // nor gethandle were... // imported into this scope 4

Użycie przestrzeni nazw W przypadku niejednoznaczności można jawnie użyć kwalifikatora zakresu :: namespace AcmeWindowSystem... typedef int Handle;... void f() using namespace sdm; // import sdm symbols using namespace AcmeWindowSystem; // import Acme symbols... // freely refer to sdm // and Acme symbols // other than Handle Handle h; // error! which Handle? sdm::handle h1; // fine, no ambiguity AcmeWindowSystem::Handle h2; // also no ambiguity... 5

Anonimowe przestrzenie nazw Anonimowa przestrzeń nazw zastępuje użycie słowa kluczowego static przy nazwie globalnej #include "header.h" namespace int a; void f() /*... */ int g() /*... */ Dostęp z zewnątrz do anonimowej przestrzeni nazw jest możliwy dzięki niejawnej dyrektywie użycia. Powyższa deklaracja jest równoważna następującej: #include "header.h" namespace $$$ int a; void f() /*... */ int g() /*... */ using namespace $$$; $$$ jest pewną nazwą unikatową w zasięgu, w którym zdefiniowana jest ta przestrzeń nazw 6

Przeszukiwanie nazw Funkcja z argumentem typu T jest najczęściej zdefiniowana w tej samej przestrzeni nazw co T. Jeżeli więc nie można znaleźć funkcji w kontekście, w którym się jej używa, to szuka się jej w przestrzeniach nazw jej argumentów namespace Chrono class Date /*... */ ; bool operator==(const Date&, const std::string&) ; std::string format(const Date&) ; // make string representation void f(chrono::date d, int i) std::string s = format(d) ; // Chrono::format() std::string t = format(i) ; // error: no format() in scope Reguła ta umożliwia pominięcie jawnego kwalifikowania nazw, co jest szczególnie istotne w przypadku argumentów funkcji operatorowych i wzorców, gdzie może to być szczególnie kłopotliwe. 7

Przeszukiwanie nazw W przypadku, kiedy funkcja przyjmuje argumenty z więcej niż jednej przestrzeni nazw, funkcje są wyszukiwane w przestrzeni nazw każdego argumentu i w zwykły sposób rozstrzyga się przeciążenie wszystkich znalezionych funkcji. Jeżeli funkcję wywołuje metoda klasy, to pierwszeństwo przed funkcjami znalezionymi przez typy argumentów mają metody tej samej klasy i jej klas bazowych. namespace Chrono class Date /*... */ ; bool operator==(const Date&, const std::string&); std::string format(const Date&) ; // make string representation void f(chrono::date d, std::string s) if (d == s) else if (d == "August 4, 1914") 8

Aliasy przestrzeni nazw Jeżeli użytkownicy nadają przestrzeniom nazw krótkie nazwy, to mogą one spowodować konflikt namespace A // short name, will clash (eventually) A::String s1 = "Grieg"; A::String s2 = "Nielsen"; Długie nazwy są niewygodne w użyciu namespace American_Telephone_and_Telegraph // too long American_Telephone_and_Telegraph::String s3 = "Grieg"; American_Telephone_and_Telegraph::String s4 = "Nielsen"; Dylemat ten można rozwiązać za pomocą krótkiego aliasu dla długiej nazwy przestrzeni nazw // use namespace alias to shorten names: namespace ATT = American_Telephone_and_Telegraph; ATT::String s3 = "Grieg"; ATT::String s4 = "Nielsen"; 9

Aliasy przestrzeni nazw Dzięki aliasom przestrzeni nazw użytkownik może także odwoływać się do biblioteki namespace Lib = Foundation_library_v2r11; Lib::set s; Lib::String s5 = "Sibelius"; Upraszcza to wymianę jednej biblioteki na inną. Używanie Lib zamiast Foundation_library_v2r11 ułatwia przejście do wersji v3r5 - wystarczy zmienić inicjowanie aliasu Lib i ponownie skompilować kod. Nadużywanie aliasów może prowadzić do nieporozumień 10

Komponowanie przestrzeni nazw Często chcemy utworzyć interfejs z istniejących już interfejsów, np.: namespace His_string class String /*... */ ; String operator+(const String&, const String&) ; String operator+(const String&, const char*) ; void fill(char) ; namespace Her_vector template<class T> class Vector /*... */ ; namespace My_lib using namespace His_string; using namespace Her_vector; void my_fct(string&) ; Teraz przy pisaniu programu można posługiwać się My_lib: void f() My_lib::String s = "Byron"; // finds My_lib::His_string::String using namespace My_lib; void g(vector<string>& vs) my_fct(vs[5]) ; 11

Komponowanie przestrzeni nazw Definiując funkcję lub daną, musimy znać prawdziwą nazwę elementu: void My_lib::fill() // error: no fill() declared in My_lib void His_string::fill() // ok: fill() declared in His_string void My_lib::my_fct(My_lib::Vector<My_lib::String>& v) // ok Idealna przestrzeń nazw powinna: wyrażać logicznie spójny zbiór cech nie dawać użytkownikom dostępu do innych cech nie stanowić znaczącego obciążenia notacyjnego dla użytkowników 12

Wybór Czasami jest potrzebny dostęp jedynie do kilku nazw z danej przestrzeni. Można napisać deklarację przestrzeni nazw, zawierającą tylko te potrzebne nazwy namespace His_string // part of His_string only class String /*... */ ; String operator+(const String&, const String&) ; String operator+(const String&, const char*) ; Jeżeli nie jest się projektantem przestrzeni His_string, łatwo można wprowadzić bałagan. Zmiana w rzeczywistej definicji przestrzeni nie znajdzie odbicia w tej deklaracji. Wyboru elementów z przestrzeni nazw można dokonać jawnie za pomocą deklaracji użycia: namespace My_string using His_string::String; using His_string::operator+; // use any + from His_string Deklaracja użycia wprowadza do zasięgu każdą deklarację o danej nazwie. Pojedyncza deklaracja użycia może wprowadzić każdy wariant funkcji przeciążonej 13

Komponowanie i wybór Łączenie komponowania (za pomocą dyrektyw użycia) z wyborem (za pomocą deklaracji użycia) zapewnia elastyczność potrzebną w praktyce. Z użyciem tych mechanizmów możemy zapewnić dostęp do wielu udogodnień, a zarazem rozwiązać problem konfliktu nazw i niejednoznaczności wynikających z komponowania namespace His_lib class String /*... */ ; template<class T> class Vector /*... */ ; namespace Her_lib template<class T> class Vector /*... */ ; class String /*... */ ; namespace My_lib using namespace His_lib; // everything from His_lib using namespace Her_lib; // everything from Her_lib using His_lib::String; // resolve potential clash in favor of His_lib using Her_lib::Vector; // resolve potential clash in favor of Her_lib template<class T> class List /*... */ ; // additional stuff 14

Komponowanie i wybór Nazwy zadeklarowane jawnie w przestrzeni nazw (łącznie z nazwami wprowadzonymi za pomocą deklaracji użycia) mają pierwszeństwo przed nazwami wprowadzonymi za pomocą dyrektyw użycia. Nazwę w nowej przestrzeni nazw można zmienić za pomocą dyrektywy typedef lub poprzez dziedziczenie namespace Lib2 using namespace His_lib; // everything from His_lib using namespace Her_lib; // everything from Her_lib using His_lib::String; // resolve potential clash in favor of His_lib using Her_lib::Vector; // resolve potential clash in favor of Her_lib typedef Her_lib::String Her_string; // rename template<class T> class His_vec // "rename" : public His_lib::Vector<T> /*... */ ; template<class T> class List /*... */ ; // additional stuff 15

Przestrzenie nazw i przeciążanie Przeciążanie działa między przestrzeniami nazw. Dzięki temu przekształcenie istniejących bibliotek do postaci z użyciem przestrzeni nazw wymaga minimalnych zmian kodu źródłowego, np. // old A.h: void f(int) ; // old B.h: void f(char) ; // old user.c: #include "A.h" #include "B.h" void g() f( a ) ; // calls the f() from B.h // new A.h: namespace A void f(int) ; // new B.h: namespace B void f(char) ; // new user.c: #include "A.h" #include "B.h" using namespace A; using namespace B; void g() f( a ) ; // calls the f()from B.h 16

Przestrzenie nazw są otwarte Przestrzeń nazw jest otwarta, tzn. można do niej dodawać nazwy w kilku deklaracjach. W ten sposób można umieszczać duże fragmenty programów w pojedynczej przestrzeni nazw. namespace A int f() ; // now A has member f() namespace A int g() ; // now A has two members, f() and g() Otwartość przestrzeni nazw jest pomocna w transformacji programów // my header: void f() ; // my function #include<stdio.h> int g() ; // my function // my header: namespace Mine void f() ; // my function #include<stdio.h> namespace Mine int g() ; // my function 17

Przestrzenie nazw są otwarte Definiując wcześniej zadeklarowaną składową przestrzeni nazw, bezpieczeniej jest użyć składni Mine:: niż ponownie otwierać przestrzeń Mine namespace Mine void f(); void Mine::ff() // error: no ff() declared in Mine Kompilator nie wykryje tego błędu przy próbie zdefiniowania ff() w ponownie otwartej przestrzeni nazw namespace Mine // reopening Mine to define functions void ff() // oops! no ff() declared in Mine; // ff() is added to Mine by this definition 18

Przestrzenie nazw i C Deklaracje funkcji i danych zdefiniowanych w plikach kompilowanych kompilatorem C należy poprzedzić w C++ deklaratorem extern "C" extern "C" int printf(const char*... ); extern "C"... int printf(const char*... );... ; W języku C++ zdefiniowano standardowe pliki nagłówkowe, w których funkcje są dostępne w przestrzeni nazw std // cstdio namespace std extern "C" int printf(const char*... ) ; 19

Funkcje o zmiennej liczbie argumentów W <cstdarg> znajduje się zbiór makrodefinicji, umozliwiających dostęp do funkcji przyjmujących zmienną liczbę argumentów Napiszmy funkcję obsługi błędów, która ma jeden argument całkowity, określający ważność błędu, po którym może wystąpić dowolna liczba łańcuchów tekstowych Komunikat o błędzie tworzony jest poprzez przekazanie każdego słowa jako osobnego argumentu łańcuchowego. Lista argumentów powinna się kończyć pustym wskaźnikiem do char 20

Funkcje o zmiennej liczbie argumentów #include <iostream> #include <cstdarg> #include <sstream> using namespace std; extern void error (int...); const char *Null_cp = 0; int main (int argc, char *argv[]) switch (argc) case 1: error (0, argv[0], Null_cp); break; case 2: error (0, argv[0], argv[1], Null_cp); break; default: ostringstream s; s << argc-1; string ss=s.str(); error (1, argv[0], "with", ss.c_str(), "arguments", Null_cp); //... void error (int severity...) // "severity" followed by a // zero-terminated list of char *s va_list ap; va_start (ap, severity); //arg startup for (;;) char *p = va_arg (ap, char *); if (p == 0) break; cerr << p << ' '; va_end (ap); // arg cleanup cerr << '\n'; if (severity)exit (severity); 21