From bf4b3cb311df5e4dc685f15f338cd27c14f82a1d Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 25 Jan 2019 21:59:00 +0100 Subject: Write a bunch of stuff about classes, add .gitignore --- .gitignore | 1 + doc/.ninja_deps | Bin 16 -> 0 bytes doc/.ninja_log | 2 - doc/quick_cplusplus.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++- doc/quick_cplusplus.pdf | Bin 212718 -> 240889 bytes 5 files changed, 95 insertions(+), 4 deletions(-) delete mode 100644 doc/.ninja_deps delete mode 100644 doc/.ninja_log diff --git a/.gitignore b/.gitignore index 0753705..2be2a5c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ **/*build **/*.swp +**/.ninja_* diff --git a/doc/.ninja_deps b/doc/.ninja_deps deleted file mode 100644 index 2afb5cc..0000000 Binary files a/doc/.ninja_deps and /dev/null differ diff --git a/doc/.ninja_log b/doc/.ninja_log deleted file mode 100644 index 891c53f..0000000 --- a/doc/.ninja_log +++ /dev/null @@ -1,2 +0,0 @@ -# ninja log v5 -0 770 1548439603 quick_cplusplus.pdf 5be4e5805f2d04b5 diff --git a/doc/quick_cplusplus.md b/doc/quick_cplusplus.md index 411e0a3..105b4e0 100644 --- a/doc/quick_cplusplus.md +++ b/doc/quick_cplusplus.md @@ -131,8 +131,12 @@ chiamata anche STL) che giustamente è chiamato `std`. `std` contiene molte cose molto utili come per esempio la `std::string`. ## Allocazione di memoria dinamica -Come sapete è spesso utile se non necessario allocare della memoria "dinamica", -ossia non controllata a tempo di compilazione. +Come sapete è spesso utile se non necessario allocare della memoria "dinamica". +A differenza del C nel C++ non ha una suddivisione cristallina tra le regioni +di memoria quindi non si parla di stack, heap e bss (in realtà ci sono ma è +meglio non pensarci troppo) ma semplicemente di memoria "statica" e +"diniamica". + In C esistono le funzioni `malloc()` e `free()` per richiedere e liberare della memoria. In C++ la funzione è stata integrata con delle *keywords* quali `new` e `delete`, che si usano come segue. @@ -145,6 +149,9 @@ int *data = new int[10]; // data = NULL; delete data; ``` +Questo permette di fare tutte le cose sporche con i puntatori come in C, ma +più avanti sarà mostrato come abbandonare questa fabbrica di codice che causa +`segmentation fault`, utilizzando una cosa chiamata RAII. ## References I puntatori del C sono molto utili, non possiamo negarlo, ma come tutti sanno @@ -243,3 +250,88 @@ Giustamente non compila, perché il compiler non sa quale delle due funzioni si vuole utilizzare. Ci propone però le varianti che ha trovato "`note: candidate`" che potrebbero essere valide. + + +# Classe: lo struct glorificato +Se ancora non lo sapevate, il C++ appartiene ad una categoria di linguaggi di +programmazione detta di paradigma *orientato ad oggetti* (Object Oriented +Programming, OOP). + +Ciò non significa che siete obbligati ad abbandonare l'amato codice lineare, +ma non potete nemmeno pretendere che l'OOP non esista. + +## Perché esiste `class` +Il concetto di classe arriva da un'altra idea chiamata *incapsulazione*. +Vediamo un esempio che ne dimostra l'utilità (importante: non si deve usare +**sempre** l'incapsulazione, si deve usare solo quando **serve**). + +Okay, quindi prendiamo questo `struct` +```C++ +struct mytime { + unsigned hour; // from 0 to 23 + unsigned min; // from 0 to 59 + unsigned sec; // from 0 to 59 +}; +``` +Molto semplice. Il problema di questo è che si può fare questo: +```C++ +mytime when_you_will_be_productive = { 23, 61, 99 }; +when_you_will_be_productive.hour = 1234; +``` +Ma come sapete, se non usate un qualche orologio esotico, le 22:61:99 non +esistono. Quindi servirebbe una cosa del genere: +```C++ +mytime make_mytime(unsigned hour, unsigned min, unsigned sec) { + if ((hour > 23) || (min > 59) || (sec > 59)) + // I'll explain this later, bear with me + throw std::runtime_error("invalid time"); + + return mytime { hour, min, sec }; +} +``` +Ma la gente, stupida com'è può comunque decidere creare degli `struct mytime` +invalidi a mano. Quindi in C++ si fa il seguente: +```C++ +class mytime { +private: + unsigned m_hour; + unsigned m_min; + unsigned m_sec; + +public: + // this is called 'constructor' + mytime(unsigned hour, unsigned min, unsigned sec); + + // these are 'member functions' + void set(unsigned hour, unsigned min, unsigned sec); + + unsigned hour(); + unsigned min(); + unsigned sec(); +} +``` +I membri dello `struct`, ora detto classe, sono stati resi "privati". +E abbiamo messo delle funzioni come membri, che si chiamano quindi *funzioni +membro*. + +Le funzioni membro hanno diritto di modificare i membri privati +(come `m_hour`), mentre il mondo esterno no. Come si presentano? +```C++ +// the variable is created by calling the constructor +mytime example(14, 23, 55); + +// we can call a member function +unsigned hour = example.hour(); + +// but we CANNOT read or assign a private member +example.m_min = 23; // compile error + +// except through a member function +example.set(16, 23, 34); +``` + +Ora, non mostro l'implementazione (nel file `.cpp`) di queste funzioni, siccome +si mostra la dichiarazione nel file header. Ma si può intuire che +`mytime::set(...)` è simile l'esempio precedente di `make_mytime(...)`, ossia +imposta i valori controllando che sono validi. Mentre le altre ritornano +semplicemente una copia del valore chiesto. diff --git a/doc/quick_cplusplus.pdf b/doc/quick_cplusplus.pdf index ac74aa3..96e3acf 100644 Binary files a/doc/quick_cplusplus.pdf and b/doc/quick_cplusplus.pdf differ -- cgit v1.2.1