29
C++ wykład 3 (7.03.2013) Składowe statyczne Funkcje wbudowane Argumenty domyślne Funkcje zaprzyjaźnione

C++ wykład 3 (7.03.2013)

  • Upload
    azize

  • View
    38

  • Download
    0

Embed Size (px)

DESCRIPTION

C++ wykład 3 (7.03.2013). Składowe statyczne Funkcje wbudowane Argumenty domyślne Funkcje zaprzyjaźnione. Pola statyczne. Każdy obiekt danej klasy ma swój własny zestaw pól z danymi. - PowerPoint PPT Presentation

Citation preview

Page 1: C++ wykład 3 (7.03.2013)

C++wykład 3 (7.03.2013)

Składowe statyczneFunkcje wbudowane

Argumenty domyślneFunkcje zaprzyjaźnione

Page 2: C++ wykład 3 (7.03.2013)

Pola statyczne

Każdy obiekt danej klasy ma swój własny zestaw pól z danymi.

Pole statyczne, z deklaratorem static, nie jest częścią obiektu, istnieje poza jakimkolwiek obiektem i jest wspólne dla wszystkich obiektów danej klasy.

Pole statyczne istnieje przez cały czas życia programu, nawet wtedy gdy nie utworzono żadnego obiektu danej klasy.

Page 3: C++ wykład 3 (7.03.2013)

Pola statyczne Deklaracja pola statycznego w ciele klasy (w pliku

nagłówkowym) nie jest jego definicją. Przykład klasy z deklaracją pola statycznego:

class data{ int dz, mies, rok;public: data (int d, int m, int r) : dz(d), mies(m), rok(r) {/*…*/} static data poczatek_kalendarza;};

Definicję pola statycznego należy umieścić poza klasą (w pliku źródłowym).

Przykład definicji pola statycznego poza klasą:data data::poczatek_kalendarza(15,10,1582);

Page 4: C++ wykład 3 (7.03.2013)

Pola statyczne

Odniesienie się do pola statycznego poprzez nazwę klasy:klasa::pole_stat

Do pola statycznego można się też odnieść poprzez jakikolwiek obiekt danej klasy:klasa ob, *wsk;// …ob.pole_statwsk->pole_stat

Page 5: C++ wykład 3 (7.03.2013)

Statyczne funkcje składowe

Statyczna funkcja składowa, z deklaratorem static, nie odnosi się do żadnego obiektu danej klasy.

Statyczna funkcja składowa może być wywołana w dowolnym momencie, nawet wtedy gdy nie utworzono żadnego obiektu danej klasy.

Deklaracja statycznej funkcji składowej znajduje się w ciele klasy (w pliku nagłówkowym) a jej definicja jest poza klasą (w pliku źródłowym).

Page 6: C++ wykład 3 (7.03.2013)

Statyczne funkcje składowe Przykład klasy z deklaracją statycznej funkcji składowej:

class data{ int dz, mies, rok;public: data (int d, int m, int r) : dz(d), mies(m), rok(r) {/*…*/} static int roznica (data p, data k);};

Przykład definicji statycznej funkcji składowej:int data::roznica (data p, data k) {/*…*/}

W ciele statycznej funkcji składowej nie wolno odnosić się do składowych instancyjnych ani do wskaźnika this.

Do statycznej funkcji składowej można odnieść się poprzez nazwę klasy albo poprzez jakikolwiek obiekt danej klasy.

Page 7: C++ wykład 3 (7.03.2013)

Funkcje wbudowane

Funkcje wbudowane, oznaczone deklaratorem inline, są rozwijane w miejscu wywołania.

Ich definicja musi być znana w momencie kompilacji a nie linkowania, dlatego nie tylko ich deklaracja ale również definicja znajduje się w pliku nagłówkowym.

Deklarator inline to tylko sugestia dla kompilatora aby wbudowywał funkcję w miejscu jej wywołania.

Funkcja inline zostanie skompilowane jako outline w przypadku, gdy: kompilujemy program do pracy z debuggerem, funkcja jest rekurencyjna, pobieramy w programie adres funkcji.

Page 8: C++ wykład 3 (7.03.2013)

Funkcje wbudowane

Wbudowywanie funkcji w kod ma sens w przypadku krótkich funkcji.

Funkcje wbudowane zwiększają rozmiar programu wynikowego ale przyspieszają jego działanie.

Przykład funkcji wbudowanej:inline int zaokraglenie (double d){ return d<0 ? int(d-.5) : int(d+.5);}

Page 9: C++ wykład 3 (7.03.2013)

Wbudowane funkcje składowe

W klasie też można definiować wbudowane funkcje składowe.

Metoda zdefiniowana w klasie jest traktowana jako inline.

Metody inline można także definiować poza klasą.

Page 10: C++ wykład 3 (7.03.2013)

Wbudowane funkcje składowe Przykład klasy z metodami wbudowanymi:

class data{ int dz, mies, r;public: data (int d, int m, int r); int dzien (void) const; int miesiac (void) const { return mies; } inline int rok (void) const { return r; }};inline data::data (int d, int m, int r): dz(d), mies(m), r(r) {}inline int data::dzien (void) const{ return dz; }

Page 11: C++ wykład 3 (7.03.2013)

Argumenty domyślne

Często mamy taką sytuację, że w ogólnym przypadku funkcja wymaga podania większej liczby argumentów niż w przypadku najprostszym, albo że wartości niektórych argumentów często się powtarzają.

Argumenty funkcji globalnych i funkcji składowych w klasie mogą posiadać argumenty domyślne.

Argumenty domyślne są formą przeciążania nazwy funkcji.

Page 12: C++ wykład 3 (7.03.2013)

Argumenty domyślne

Argumenty domyślne mogą występować tylko na końcu listy argumentów.

Wartości domyślne nadawane argumentom domyślnym podaje się tylko w deklaracji funkcji, w definicji się tego nie powtarza.

Przy wywoływaniu funkcji z argumentami domyślnymi można pomijać argumenty domyślne od końca.

Wszystkie argumenty mogą być domyślne.

Page 13: C++ wykład 3 (7.03.2013)

Argumenty domyślne

Przykład funkcji z argumentem domyślnym:// deklaracjavoid drukuj (int x, int podst=10);// definicjavoid drukuj (int x, int podst) {/*…*/}// wywołaniadrukuj(63); // wynik 63drukuj(63,16); // wynik 3Fdrukuj(63,2); // wynik 111111

Page 14: C++ wykład 3 (7.03.2013)

Nienazwane argumenty

Jeśli argumentu nazwanego nie używa się w ciele funkcji lub funkcji składowej, to kompilator będzie generował ostrzeżenia.

Argumenty, których nie używa się w ciele funkcji mogą nie posiadać swojej nazwy.

Również argumenty domyślne mogą nie posiadać nazwy.

Przykład funkcji z nienazwanym argumentem:void buczenie (int) { /*…*/ }

Page 15: C++ wykład 3 (7.03.2013)

Funkcja bez argumentów

Jeśli funkcja nie ma żadnych argumentów, to powinno się ją zadeklarować z argumentem void.

Przykład:void buczenie (void);// to jest równoważne z// void buczenie ();// w języku C byłoby to równoważne z // void buczenie (...);

Page 16: C++ wykład 3 (7.03.2013)

Funkcje zaprzyjaźnione

Problem z kwiatkami w domu w czasie dalekiej podróży służbowej.

Funkcja, która jest przyjacielem klasy, ma dostęp do wszystkich jej prywatnych i chronionych składowych.

To klasa deklaruje, które funkcje są jej przyjaciółmi.

Deklaracja przyjaźni może się pojawić w dowolnej sekcji i jest poprzedzona słowem kluczowym friend.

Page 17: C++ wykład 3 (7.03.2013)

Funkcje zaprzyjaźnione Przykład klasy z funkcją zaprzyjaźnioną:

// klasa z funkcją zaprzyjaźnionąclass pionek{ int x, y; // … friend void raport (const pionek &p);};// funkcja, która jest przyjacielem klasyvoid raport (const pionek &p){ cout << "(" << p.x << ", " << p.y << ")";}

Page 18: C++ wykład 3 (7.03.2013)

Funkcje zaprzyjaźnione

Nie ma znaczenia, w której sekcji (prywatnej, chronionej czy publicznej) pojawi się deklaracja przyjaźni.

Funkcja zaprzyjaźniona z klasą nie jest jej składową, nie może używać wskaźnika this w stosunku do obiektów tej klasy.

Jedna funkcja może się przyjaźnić z kilkoma klasami.

Istotą przyjaźni jest dostęp do niepublicznych składowych w klasie – sensowne jest deklarowanie przyjaźni, gdy dana funkcja pracuje z obiektami tej klasy.

Page 19: C++ wykład 3 (7.03.2013)

Funkcje zaprzyjaźnione

Można także umieścić w klasie nie tylko deklarację funkcji zaprzyjaźnionej, ale również jej definicję; tak zdefiniowana funkcja: jest nadal tylko przyjacielem klasy; jest inline; może korzystać z typów zdefiniowanych w klasie.

Funkcją zaprzyjaźnioną może być funkcja składowa z innej klasy.

Page 20: C++ wykład 3 (7.03.2013)

Klasy zaprzyjaźnione

Możemy w klasie zadeklarować przyjaźń z inną klasą, co oznacza, że każda metoda tej innej klasy jest zaprzyjaźniona z klasą pierwotną.

Przykład:class A{ friend class B; // …};

Przyjaźń jest jednostronna. Przyjaźń nie jest przechodnia. Przyjaźni się nie dziedziczy.

Page 21: C++ wykład 3 (7.03.2013)

Klasy zaprzyjaźnione

Dwie klasy mogą się przyjaźnić z wzajemnością:class A;class B{ friend class A; // …};class A{ friend class B; // …};

Page 22: C++ wykład 3 (7.03.2013)

Nowości z C++11 – wskaźnik pusty nullptr Wskaźnik pusty nullptr – zastępuje makro NULL albo 0. Motywacja: w C NULL jest makrem preprocesora zdefiniowanym

jako ((void*)0); w C++ niejawna konwersja z void* do wskaźnika innego typu jest niedozwolona, więc nawet takie proste przypisanie jak char* c = NULL mogłoby być w tym przypadku błędem kompilacji.

Sytuacja komplikuje się w przypadku przeciążania:void foo(char*);void foo(int);Gdy programista wywoła foo(NULL), to wywoła wersję foo(int), która prawie na pewno nie była przez niego zamierzona.

nullptr nie może być przypisane do typów całkowitych, ani porównywane z nimi; może być porównywane z dowolnymi typami wskaźnikowymi.

Page 23: C++ wykład 3 (7.03.2013)

Nowości z C++11 – pętla for oparta na zakresie Zakresy reprezentują kontrolowaną listę pomiędzy dwoma jej punktami.

Kontenery uporządkowane są nad zbiorem koncepcji zakresu i dwa iteratory w kontenerze uporządkowanym także definiują zakres.

Nowa pętla for została stworzona do łatwej iteracji po zakresie; jej ogólna postać jest następująca:for (TYP &x: kolekcja<TYP>) instrukcja;

Przykład:int moja_tablica[5] = {1, 2, 3, 4, 5};for(int &x: moja_tablica) { x *= 2; }

Pierwsza sekcja nowego for (przed dwukropkiem) definiuje zmienną, która będzie użyta do iterowania po zakresie. Zmienna ta, tak jak zmienne w zwykłej pętli for, ma zasięg ograniczony do zasięgu pętli.

Druga sekcja (po dwukropku), reprezentuje iterowany zakres. W tym przypadku, zwykła tablica jest konwertowana do zakresu. Mógłby to być na przykład std::vector albo inny obiekt spełniający koncepcję zakresu.

Page 24: C++ wykład 3 (7.03.2013)

Nowości z C++11 – uogólnione wyrażenia stałe

Stałe wyrażenia zawsze zwracają ten sam wynik i nie wywołują żadnych dodatkowych efektów ubocznych – są one dla kompilatorów okazją do optymalizacji, ponieważ kompilatory często wykonują te wyrażenia w czasie kompilacji i wstawiają ich wyniki do programu.

Słowo kluczowe constexpr pozwala programiście zagwarantować, że funkcja lub konstruktor obiektu są stałymi podczas kompilacji.

Page 25: C++ wykład 3 (7.03.2013)

Nowości z C++11 – uogólnione wyrażenia stałe Zastosowanie constexpr do funkcji narzuca bardzo

ścisłe ograniczenia na to, co funkcja może robić: funkcja musi posiadać typ zwracany różny od void; zawartość funkcji musi być postaci return wyrażenie; wyrażenie musi być stałym wyrażeniem po zastąpieniu

argumentu (to stałe wyrażenie może albo wywołać inne funkcje tylko wtedy, gdy te funkcje też są zadeklarowane ze słowem kluczowym constexpr albo używać inne stałe wyrażenia);

wszystkie formy rekurencji w stałych wyrażeniach są zabronione; funkcja zadeklarowana ze słowem kluczowym constexpr nie

może być wywoływana, dopóki nie będzie zdefiniowana w swojej jednostce translacyjnej.

Przykład:constexpr int GetFive() {return 5;}int someValues[GetFive() + 5];

Page 26: C++ wykład 3 (7.03.2013)

Nowości z C++11 – uogólnione wyrażenia stałe Zmienne stałowyrażeniowe typu constexpr są niejawnie typu const –

mogą one przechować wyniki wyrażeń stałych lub stałowyrażeniowych konstruktorów (czyli zdefiniowanych ze słowem kluczowym constexpr).

Przykład:constexpr double grawitacja = 9.8;constexpr double grawitacjaKsiezyca = grawitacja / 6;

Stałowyrażeniowy konstruktor służy do konstrukcji wartości stałowyrażeniowych z typów zdefiniowanych przez użytkownika, konstruktory takie muszą być zadeklarowane jako constexpr.

Stałowyrażeniowy konstruktor musi być zdefiniowany przed użyciem w jednostce translacyjnej (podobnie jak metoda stałowyrażeniowa) i musi mieć puste ciało funkcji i musi inicjalizować swoje składowe za pomocą stałych wyrażeń.

Destruktory takich typów powinny być trywialne.

Page 27: C++ wykład 3 (7.03.2013)

Nowości z C++11 – referencja do r-wartości Obiekty tymczasowe (określane jako r-wartości), to

wartości stojące po prawej stronie operatora przypisania (analogicznie zwykła referencja do zmiennej stojącej po lewej stronie przypisania nazywa się l-wartością).

Argument w funkcji będący referencją do r-wartości definiujemy jako TYP &&arg.

Argument będący r-referencją może być akceptowany jako niestała wartość, co pozwala funkcjom na ich modyfikację.

Argumenty r-referencyjne umożliwiają pewnym obiektom na stworzenie semantyki przenoszenia za pomocą konstruktorów przenoszących definiowanych jako TYP::TYP (TYP &&arg) oraz przypisań przenoszących.

Page 28: C++ wykład 3 (7.03.2013)

Nowości z C++11 – referencja do r-wartości Przykład:

class Simple { void *Memory; // The resourcepublic: Simple() { Memory = nullptr; } // the MOVE-CONSTRUCTOR Simple(Simple&& sObj) { // Take ownership Memory = sObj.Memory; // Detach ownership sObj.Memory = nullptr; } Simple(int nBytes) { Memory = new char[nBytes]; } ~Simple() { if(Memory != nullptr) delete[] Memory; }};

Page 29: C++ wykład 3 (7.03.2013)

Nowości z C++11 – referencja do r-wartości Przykład:

Simple GetSimple() { Simple sObj(10); return sObj; }

// R-Value NON-CONST referencevoid SetSimple(Simple&& rSimple) { // performing memory assignment here Simple object; object.Memory = rSimple.Memory; rSimple.Memory = nullptr; // Use object... delete[] object.Memory; }