Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Poprzednia wersja
Nowa wersja
Poprzednia wersja
pl:dydaktyka:jimp2:2017:labs:operatory [2017/04/04 00:52]
mwp [Wykorzystanie przeciążania operatorów]
pl:dydaktyka:jimp2:2017:labs:operatory [2019/06/27 15:50] (aktualna)
Linia 7: Linia 7:
  
 Dla typów zdefiniowanych przez programistę można zdefiniować (przeciążyć) operatory istniejące w języku C%%++%% dla danego typu, dzięki czemu stosowanie ich w kontekście tych typów ma sens. Jednym z typowych przykładów przeciążania operatorów jest przeładowanie operatora wstawiania i pobierania danych ze strumienia:<​file cpp Point.h>//​ Deklaracja znajduje się w pliku Point.h Dla typów zdefiniowanych przez programistę można zdefiniować (przeciążyć) operatory istniejące w języku C%%++%% dla danego typu, dzięki czemu stosowanie ich w kontekście tych typów ma sens. Jednym z typowych przykładów przeciążania operatorów jest przeładowanie operatora wstawiania i pobierania danych ze strumienia:<​file cpp Point.h>//​ Deklaracja znajduje się w pliku Point.h
-#​ifndef ​PUNKT_H +#​ifndef ​POINT_H 
-#​define ​PUNKT_H+#​define ​POINT_H
 #include <​iostream>​ #include <​iostream>​
  
Linia 21: Linia 21:
     //dostępu do prywatnych pól z wewnątrz definicji     //dostępu do prywatnych pól z wewnątrz definicji
     //funkcji zadeklarowanej poniżej     //funkcji zadeklarowanej poniżej
-//    friend std::​istream&​ operator>>​(std::​istream &, ​Punkt&);+//    friend std::​istream&​ operator>>​(std::​istream &, ​Point&);
     ...     ...
     ​     ​
Linia 33: Linia 33:
 std::​istream&​ operator>>​(std::​istream &is, Point& point); std::​istream&​ operator>>​(std::​istream &is, Point& point);
 #endif #endif
-</code>+</file>
  
 I definicja w pliku Point.cpp I definicja w pliku Point.cpp
 <file cpp Point.cpp>​ <file cpp Point.cpp>​
 //Definicja w Point.cpp //Definicja w Point.cpp
-#include "punkt.h"+#include "Point.h"
 #include <​iomanip>​ #include <​iomanip>​
 #include <​iostream>​ #include <​iostream>​
  
 using ::​std::​istream;​ using ::​std::​istream;​
 +using ::std::ws;
  
 //Helper functions: //Helper functions:
-void CheckNextChar(char c, istream *is) { +void CheckNextChar(char c, istream* is) { 
-  int next_char = is.peek();+  int next_char = is->peek();
   if (next_char != c) {   if (next_char != c) {
     throw runtime_error("​invalid character"​);​     throw runtime_error("​invalid character"​);​
   }   }
-  is.ignore();+  is->ignore();
 } }
  
-void IgnoreWhitespace(istream *is) { +void IgnoreWhitespace(istream* is) { 
-  is >> ws;+  ​(*is>> ws;
 } }
  
-double ReadNumber(istream *is) {+double ReadNumber(istream* is) {
   double d;   double d;
-  is >> d;+  ​(*is>> d;
   return d;   return d;
 } }
Linia 68: Linia 69:
 //wewnątrz funkcji (STL nie używa naszej konwencji z przekazywaniem ​ //wewnątrz funkcji (STL nie używa naszej konwencji z przekazywaniem ​
 //przez wskaźnik) //przez wskaźnik)
-istream&​ operator>>​(istream & input, ​Punkt& p){+istream&​ operator>>​(istream & input, ​Point& p){
     CheckNextChar('​(',​ &​input);​     CheckNextChar('​(',​ &​input);​
     p.SetX(ReadNumber(&​input));​     p.SetX(ReadNumber(&​input));​
Linia 77: Linia 78:
     return input; ​     // Umożliwia cin >> a >> b >> c;     return input; ​     // Umożliwia cin >> a >> b >> c;
 } }
-</code>+</file>
  
 Powyższy przykład umożliwia wczytanie punktu podanego w formacie //(12, 22)//. Należy zwrócić uwagę, że operator ">>"​ nie może być metodą klasy a funkcją zaprzyjaźnioną jeśli chcemy wywołać go jako <code cpp>cin >> punkt;</​code> ​ Jeśli operator zadeklarowany byłby jako metoda klasy trzeba by go wywoływać na przykład tak:<​code cpp>​punkt >> cin</​code>​ Powyższy przykład umożliwia wczytanie punktu podanego w formacie //(12, 22)//. Należy zwrócić uwagę, że operator ">>"​ nie może być metodą klasy a funkcją zaprzyjaźnioną jeśli chcemy wywołać go jako <code cpp>cin >> punkt;</​code> ​ Jeśli operator zadeklarowany byłby jako metoda klasy trzeba by go wywoływać na przykład tak:<​code cpp>​punkt >> cin</​code>​
  
 ===== Jak to działa ===== ===== Jak to działa =====
-Operatory to "​zwyczajne"​ funkcje w jezyku ​C%%++%%. Kompilator zamienia każde pojawienie ​sie operatora na wywołanie odpowiedniej funkcji.  ​+Operatory to "​zwyczajne"​ funkcje w języku ​C%%++%%. Kompilator zamienia każde pojawienie ​się operatora na wywołanie odpowiedniej funkcji.  ​
  
-Zakładajac ​że operatory + oraz * są składowymi klas, tak będzie wyglądało ​uzycie ​tych operatorów dla kompilatora:​+Zakładając ​że operatory + oraz * są składowymi klas, tak będzie wyglądało ​użycie ​tych operatorów dla kompilatora:​
 <code cpp> <code cpp>
 Matrix a, b; Matrix a, b;
-a + b; // Dla kompilatora oznacza to a.operator+(b);​ +a + b; // Dla kompilatora oznacza to a.operator+(b); ​(argument a zostanie przesłany jako this do funkcji) 
-a * b; // dla kompilatora oznacza to a.operator*(b);​+a * b; // dla kompilatora oznacza to a.operator*(b); ​(j.w.)
 </​code>​ </​code>​
  
-Można ​takze zdefiniować niektóre operatory jako funkcje ​zaprzyjaźnione ​(jak w przykładzie z poprzedniej sekcji). Zakłądjąc że operatoruy ​+ i * są zadeklarowane jako funkcje zaprzyjaźnione,​ tak będzie wyglądało ​uzycie ​tych operatorów dla kompilatora:​+Można ​także ​zdefiniować niektóre operatory jako funkcje ​nieskładowe ​(jak w przykładzie z poprzedniej sekcji). Zakłądjąc że operatory ​+ i * są zadeklarowane jako funkcje zaprzyjaźnione,​ tak będzie wyglądało ​użycie ​tych operatorów dla kompilatora:​
 <code cpp> <code cpp>
 Matrix a, b; Matrix a, b;
 a + b; // Dla kompilatora oznacza to operator+(a,​b);​ a + b; // Dla kompilatora oznacza to operator+(a,​b);​
 a * b; // dla kompilatora oznacza to operator*(a,​b);​ a * b; // dla kompilatora oznacza to operator*(a,​b);​
 +cin >> a; // dla kompilatora oznacza to operator>>​(cin,​ a)
 +cin >> a >> b; // dla kompilatora oznacza to operator>>​( operator>>​(cin,​ a), b)
 +//stąd też wynika, że wartość zwracana przez funkcję operator>>​ musi być taka sama jak pierwszy argument tej funkcji
 </​code>​ </​code>​
  
 ===== Operatory jedno- i dwuargumentowe===== ===== Operatory jedno- i dwuargumentowe=====
-Operatory **jednoargumentowe** można przeciążyć za pomocą niestatycznej funkcji składowej nie pobierającej żadnych argumentów lub za pomocą funkcji nie będącej składową klasy, ​obierającą jeden argument który jest obiektem lub referencją do obiektu tej klasy. **Wyjątkiem** jest operator rzutowania, który NIE może być zadeklarowany jako funkcja ​zaprzyjaźniona.+Operatory **jednoargumentowe** można przeciążyć za pomocą niestatycznej funkcji składowej nie pobierającej żadnych argumentów ​(jeden niejawny argument jest przekazywany jako **this**) ​lub za pomocą funkcji nie będącej składową klasy, ​pobierającą jeden argumentktóry jest obiektem ​(przekazywanie przez wartość) ​lub referencją do obiektu tej klasy. **Wyjątkiem** jest operator rzutowania, który NIE może być zadeklarowany jako funkcja ​nieskładowa.
  
-Załóżmy, ​ze klasa Napis jest naszą wersją klasy //string//, przechowującej napisy i umożliwiającą manipulowanie nimi. Chcąc zdefiniować na przykład operator **!**  dla klasy Napis, który będzie zwracał //true// jeśli obiekt będzie zawierał pusty napis a w każdym innym przypadku //true//, możemy to zrobić na da sposoby:+Funkcje nieskładowe mogą być dodatkowo deklarowane jako zaprzyjaźnione z klasą dla której są zdefiniowane wtedy mają dostęp do prywatnych składników klasy.  
 + 
 +Załóżmy, ​że klasa Text jest naszą wersją klasy //string//, przechowującej napisy i umożliwiającą manipulowanie nimi. Chcąc zdefiniować na przykład operator **!** (logiczne zaprzeczenie) ​dla klasy Napis, który będzie zwracał //true// jeśli obiekt będzie zawierał pusty napisa w każdym innym przypadku //true//, możemy to zrobić na da sposoby:
  
 <code cpp> <code cpp>
-class Napis{+class Text{
   public:   public:
     // składowa klasy     // składowa klasy
     bool operator!() const;     bool operator!() const;
-    // LUB funkcja zaprzyjaźniona +    // LUB (opocjonalnie) ​funkcja ​nieskładowa ​zaprzyjaźniona 
-    friend bool operator!()(const ​Napis&)+//    ​friend bool operator!()(const ​Text&)
     ...     ...
-};</​code>​+};
  
-Operatory **dwuargumentowe** można przeciążyć za pomocą niestatycznej funkcji składowej klasy pobierającej jeden argument lub za pomocą funkcji nie będącej składową klasy, ​obierającą dwa argumenty z których jeden jest obiektem lub referencją do obiektu tej klasy. **Wyjątkami** są operatory przypisania,​ **[]** oraz **->**, które NIE gogą być zadeklarowane jako funkcje zaprzyjaźniona.+  //LUB funkcja nieskładowa,​ która dodatkowo może być zaprzyjaźniona  
 +//bool operator!()(const Text &​text) 
 +</​code>​ 
 + 
 +Operatory **dwuargumentowe** można przeciążyć za pomocą niestatycznej funkcji składowej klasy pobierającej jeden argument ​(pierwszy argument jest przekazywany niejawnie jako **this**) ​lub za pomocą funkcji nie będącej składową klasy, ​pobierającą dwa argumenty z których jeden jest obiektem lub referencją do obiektu tej klasy. **Wyjątkami** są operatory przypisania,​ **[]** oraz **->**, które NIE mogą być zadeklarowane jako funkcje zaprzyjaźnione.
  
 <code cpp> <code cpp>
-class Napis{+class Text{
   public:   public:
     // składowa klasy (pomysl dlaczego zwracamy const)     // składowa klasy (pomysl dlaczego zwracamy const)
-    const Napis operator+=(const ​Napis&);+    const Text operator+=(const ​Texttxt);
     // LUB funkcja zaprzyjaźniona     // LUB funkcja zaprzyjaźniona
-    friend const Napis operator+=()(Napis&, const Napis&)+    friend const Text operator+=()(Textlhs, const Textrhs);
     ...     ...
-};</​code>​+}; 
 +const Text operator+=()(Text&​ lhs, const Text& rhs); 
 +</​code>​
  
 =====Konwersja typów===== =====Konwersja typów=====
 Specyficznym rodzajem operatorów są tzw. operatory rzutowania. Wykorzystywane one są do konwersji typów, czy inaczej mówiąc do rzutowania. W prosty sposób można rzutować pomiędzy typami wbudowanymi:​ Specyficznym rodzajem operatorów są tzw. operatory rzutowania. Wykorzystywane one są do konwersji typów, czy inaczej mówiąc do rzutowania. W prosty sposób można rzutować pomiędzy typami wbudowanymi:​
 <code cpp> <code cpp>
-double ​liczba_double ​= 12.34; +double ​number ​= 12.34; 
-int liczba_int ​(int)licczba_double;+int integer_value ​static_cast<​int>(number);
 </​code>​ </​code>​
 Aby możliwe było rzutowanie pomiędzy typami zdefiniowanymi przez programistę,​ konieczna jest definicja operatorów realizujących taką funkcjonalność. Aby możliwe było rzutowanie pomiędzy typami zdefiniowanymi przez programistę,​ konieczna jest definicja operatorów realizujących taką funkcjonalność.
 Operatory rzutowania NIE mogą być zadeklarowane jako funkcje zaprzyjaźnione - muszą być składowymi klasy. Dodatkowo niczego nie zwracają: Operatory rzutowania NIE mogą być zadeklarowane jako funkcje zaprzyjaźnione - muszą być składowymi klasy. Dodatkowo niczego nie zwracają:
 <code cpp> <code cpp>
 +//Complex.h
 class Complex{ class Complex{
   public:   public:
Linia 139: Linia 152:
     ...     ...
 }; };
 +//​Complex.cpp
 +Complex::​operator Matrix() const {
 +   ​return Matrix {{*this}};
 +}
 </​code>​ </​code>​
  
Linia 197: Linia 214:
 |.|.*|::​|?:​|sizeof| |.|.*|::​|?:​|sizeof|
  
 +===== Czy przeciążyć operator =====
 +
 +Zasadniczo jeśli zastosowanie operatora w kodzie używającym danego obiektu (wywołującym metody) jest czytelne, jednoznaczne i intuicyjne wtedy można rozważyć przeciążenie operatora dla danego typu. W przeciwnym wypadku nie należy na siłę deklarować kodu operatorów,​ gdyż pogorszą one tylko jakość i czytelność kodu.
 +
 +===== Dodatkowy rozszerzony opis =====
 +
 +Zapoznać się z opisem na stronie [[http://​en.cppreference.com/​w/​cpp/​language/​operators|Operatory]]. Na tej stronie są dodatkowe przykłady.
 ======Ćwiczenia====== ======Ćwiczenia======
-  - [1 plus] Przetestować operator wczytywania dla klasy Punkt dopisz ​operator wypisania ("<<"​). ​Sprawdź ​w jakich przypadkach ten operator się wywołuje. +  - [1 plus] Przetestować operator wczytywania dla klasy Point dopisać ​operator wypisania ("<<"​). ​Sprawdzić ​w jakich przypadkach ten operator się wywołuje. (Przetestować zarówno na cout, cin, jak i stringstream)
-  - Do klasy tablica dynamiczna DTab (laboratorium ​[[.:klasy1|Klasy i obiekty I]]):  +  - Napisać klasę Student ​polami id, first_name, last_name, program, year, gdzie wszystkie pola poza year są typu string, a pole year ma własny typ StudyYear.  
-    - [1 plus] dopisz ​operator '​[]'​ pozwalający na pobranie ​danego elementu tablicy za pomocą konstrukcji <code cpp>DTab d(10); +    - [1 plus] zdefiniować operator %%++%% i %%--%% pre(in|de)krementacji dla StudyYear 
-cout << d[5] << endl;</​code>​ +    - [2 plus] zdefiniować operator << i >> zapisu i odczytu ze strumienia, przy następujących formatach:​ 
-    - [1 plus] Jak zrobić żeby dało się ustawić element tablicy za pomocą tego operatora, ​nie tylko go pobrać?:<code cpp>tab[2= 7//ustawia 2 element tablicy na wartość 7</​code>​ +      * StudyYear - 2 
-    - [1 plus] dopisz operator ​przypisania ( = ) +      * Student - Student {id: "​2030001234",​ first_name: "​Arkadiusz",​ last_name: "​Kowalski",​ program: "​informatyka",​ year: 2} 
-    - [1 plusdopisz operatory ​<< ​>>. Przyjmij format pobierania tablicy jako <​code>​[1,2,3,4]</​code>​ +      * StudentRepository - [Student {id: "​203000001",​... , Student {id"...] 
-    - [1 plusdopisz ​operator <nowiki>++</nowiki> ​umożliwiający rozszerzenie tablicy o 1 +    - [1 pluszdefiniować operator == porównywania dla StudyYear, Student i StudentRepository i < dla StudyYear 
-  ​- [plus] Wykorzystując klasę ​//Matrix// napisz dla klasy //Complex// operator rzutowania:<code cpp>Complex c("5i3"); +    - [1 plus] zdefiniować ​operator '​[]' ​zakresu ​pozwalający na pobranie ​z repozytorium studenta o określonym id 
-Matrix nowa = (Matrix)c+    - [1 plus] co należy ​zrobić ​z powyższym operatorem, ​żeby była możliwa operacja ​<code cpp>repository["​201500022324"​].ChangeFirstName("​Ziemowit"​);</​code> ​i została zmienione imię studenta już w repozytorium. 
-</​code>​ +    - [1 plus] dopisz operator ​rzutowania dla StudyYear do typu int. 
-  - **[5 punktów] Napisz klasę ​Mapa, która będzie zawierać ​listę obiektów typu ParaKlasa Para powinna ​posiadać dwa pola jedno typu //string// a drugie typu //integer//. Klasa Mapa powinna mieć konstruktor ​przyjmujący jako parametr ścieżkę do pliku tekstowego. W konstruktorze ​powinno nastąpić odczytanie ​pliku i zbudowanie indeksu wyrazów, tak aby każdy wyraz z pliku miał odpowiadający sobie obiekt ​klasy Para liście. Pole typu //string// wewnątrz obiektów ​Para powinno odpowiadać danemu słowu, natomiast pole typu //integer// ilości powtórzeń tego słowa ​we wczytanym plikuPlik jest __dowolnym ​plikiem tekstowym!__ Analizując go, ignorujemy znaki interpunkcyjne,​ spacje tabulatory, etc. i wczytujemy tylko słowa. ** +  - [2 plusyZdefiniować klasę Zipper ze statyczną metodą zip(std::​vector<std::​string>,​ std::vector<int>), która pozwoli na uruchomienie następującego kodu: <​code ​cpp>int foo(const vector<​string>​ &v1const vector<​int>​ &v2) { 
-    * Przeładuj operator klasy Mapa **[]** tak aby możliwe było poniższe wywołanie:<​code cpp>Mapa m("​myfile,txt"​);​ +for (const pair<​string,int> &p : Zipper::​zip(v1,v2)) { 
-// w zmiennej ​ilosc powinna znaleźć się ilość powtórzeń+  if (p.first == "​elo"​) { 
 +     ​return p.second+4
 +  } 
 +
 +return 0; 
 +}</​code> ​ ​Podpowiedź:​ udostępniona też [[http://​coliru.stacked-crooked.com/​a/​ff24fd32a47a6e18|TU]] <code cpp>#​include <​iostream>​ 
 +#include <​string>​ 
 +#include <​vector>​ 
 +#include <​utility>​ 
 + 
 +using std::​cout;​ 
 +using std::​endl;​ 
 +using std::​vector;​ 
 +using std::​string;​ 
 +using std::​pair;​ 
 +using std::​literals::​string_literals::​operator""​s;​ 
 + 
 + 
 +class ZipperIterator { 
 +  public: ​   
 +   pair<string,intoperator*() const; //wmagane w linii 74 
 +   ​ZipperIterator &​operator++(); //wymagane w linii 73 for(_;​_;​TU) 
 +   bool operator!=(const ZipperIterator &other) const; //wymagane w linii 73 for(_;​TU;​_) 
 +  private: 
 +   //​TODO 
 +}; 
 + 
 +//umożliwia przeglądanie dwóch wektorów na raz, w jednej pętli range-for 
 +class Zipper { 
 +  ​public: 
 +   ​static Zipper zip(const vector<​string>​ &vs, const vector<​int>​ &vi); 
 +    
 +   ​ZipperIterator begin(); //wymagane w linii 73 for(TU;​_;​_) 
 +   ​ZipperIterator end(); //wymagane w linii 73 for(_;​TU;​_) 
 +  private: 
 +   //​TODO 
 +}; 
 + 
 + 
 + 
 +int main() 
 +
 +    vector<​int>​ vi = {1,2,3}; 
 +    vector<​string>​ vs = {"​one"​s,"​two"​s,"​three"​s};​ 
 +     
 +    ​//PROSTY przykład 
 +    for (const auto i : vi) { 
 +      cout << i;    
 +    } 
 +    cout << endl; 
 +    ​//to samo bez auto: 
 +    for (const int i : vi) { 
 +      cout << i;    
 +    } 
 +    cout << endl; 
 +    ​//przetłumaczony powyższa petla mniej wiecej tak jak to kompilator  
 +    ​//rozumie: 
 +    for (vector<int>::iterator it = vi.begin(); it != vi.end(); ++it) { 
 +      const int i = *it; 
 +      cout << i; 
 +    } 
 +    cout << endl; 
 +     
 +    //Przykład z zipperem 
 +    for (const auto &p : Zipper::​zip(vs,​vi)) { 
 +      cout << p.second << ​" ​is " ​<< p.first; 
 +    } 
 +    cout << endl; 
 +    //to samo bez auto: 
 +    for (const pair<​string,​int>​ &p : Zipper::​zip(vs,​vi)) { 
 +      cout << p.second << " is " << p.first
 +    } 
 +    cout << endl; 
 +     
 +    //​przetłumaczony powyższa petla mniej wiecej tak jak to kompilator  
 +    //​rozumie:​ 
 +    Zipper tmp  ​Zipper::​zip(vs,vi); 
 +    for (ZipperIterator it = tmp.begin();​ it != tmp.end(); ++it) { 
 +      const pair<​string,​int>​ &p = *it; 
 +      cout << p.second << " is " << p.first; 
 +    } 
 +    cout << endl; 
 +}</​code>​ 
 + 
 +  - **[5 punktów] Napisz klasę ​WordCounter (podobne ćwiczenie było już tylko jako struktura z języka C, tym razem ma być to pełna klasa z C%%++%%), która będzie zawierać ​licznik słów. Należy zdefiniować klasę Word, która będzie stanowiła klucz (słowo zliczane) i klasę Counts, która będzie przechowywała liczbę zliczeńZarówno klasa Word i Counts ​powinna ​zawierać pojedynczy typ prymitywny. Klasa WordCounter ​powinna mieć konstruktor ​domyślny inicjalizujący pusty słownik i konstruktor z listą inicjalizacyjną pozwalający zliczyć podane słowa. Dodatkowo należy zdefiniować statyczną funkcję FromInputStream przyjmującą jako parametr istream pokazujący na tekst. W funkcji FromInputStream ​powinno nastąpić odczytanie ​tekstu ​i zbudowanie indeksu wyrazów, tak aby każdy wyraz z pliku miał odpowiadający sobie obiekt ​std::​pair<​Word,​Counts> ​dowolnym kontenerze c%%++%%. Pole typu //string// wewnątrz obiektów ​Word powinno odpowiadać danemu słowu, natomiast pole typu //​integer// ​wewnątrz Counts ​ilości powtórzeń tego słowa ​w wewnętrznym słownikuZawartość strumienia ​jest __dowolnym ​tekstem!__ Analizując go, ignorujemy znaki interpunkcyjne,​ spacje tabulatory, etc. i wczytujemy tylko słowa. ** 
 +    * Przeładuj operator klasy WordCounter ​**[]** tak aby możliwe było poniższe wywołanie:<​code cpp>std::​ifstream is ("​myfile.txt"); 
 +WordCounter wc = WordCounter.FromInputStream(&​is); 
 +// w zmiennej ​ilość ​powinna znaleźć się ilość powtórzeń
 // słowa "​programowanie"​ w pliku "​myfile.txt"​ // słowa "​programowanie"​ w pliku "​myfile.txt"​
-int ilosc = m["​programowanie"​];</​code>​  +int ilosc = wc["​programowanie"​];</​code>​  
-    * Przeładuj operator **%%<<​%%** dla klasy Mapa, aby możliwe było wyświetlenie raportu o ilości słów i ich liczebności w danym pliku. Dane wyświetlane powinny być posortowane malejąco. Do tego celu wykorzystaj metodę //[[http://www.cplusplus.com/reference/list/list/sort/|sort]]// ​klasy //list// - wykorzystaj ​listę ​z biblioteki standardowej!. +    * Przeładuj operator **%%<<​%%** dla klasy WordCounter, aby możliwe było wyświetlenie raportu o ilości słów i ich liczebności w danym pliku. Dane wyświetlane powinny być posortowane malejąco. Do tego celu wykorzystaj metodę //[[http://en.cppreference.com/w/cpp/algorithm/​sort|sort]]// ​z biblioteki ​//algorithm// - wykorzystaj ​dowolny kontener ​z biblioteki standardowej! ​(w dokumentacji w przykładzie na dole jest przykład jak użyć dowolnego warunku porównującego w konteście sortowania, zerknąć na przykład środkowy z użyciem struktury customLess)
-    * Przeładuj operatory porównania (//<,>,​==//) i przypisania (//=//) dla klasy Para (porównywanie względem liczebności). +    * Przeładuj operatory porównania (//<,>,​==//​) dla klasy Counts ​(porównywanie względem liczebności). 
-    * Przeładuj operator **%%++%%** dla klasy Para, tak aby można było szybko inkrementować liczebność danego słowa podczas budowania ​mapy.+    * Przeładuj operator **%%++%%** dla klasy Counts, tak aby można było szybko inkrementować liczebność danego słowa podczas budowania ​licznika. 
 +    * Zdefiniuj funkcje DistinctWords zwaracającą ilość różnych słów w liczniku 
 +    * Zdefiniuj funkcje TotalWords zwaracającą ilość słów w liczniku z uwzględnieniem ich liczności (DistinctWords <= TotalWords) 
 +    * Zdefiniuj funkcje Words zwarającą zbiór wszystkich słów w liczniku
  
pl/dydaktyka/jimp2/2017/labs/operatory.1491259926.txt.gz · ostatnio zmienione: 2019/06/27 15:52 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0