diff options
-rw-r--r-- | bash.html.markdown | 62 | ||||
-rw-r--r-- | c++.html.markdown | 126 | ||||
-rw-r--r-- | it-it/c++-it.html.markdown | 720 | ||||
-rw-r--r-- | perl6.html.markdown | 5 |
4 files changed, 879 insertions, 34 deletions
diff --git a/bash.html.markdown b/bash.html.markdown index 4c50c653..ee783c14 100644 --- a/bash.html.markdown +++ b/bash.html.markdown @@ -32,40 +32,40 @@ echo Hello world! echo 'This is the first line'; echo 'This is the second line' # Declaring a variable looks like this: -VARIABLE="Some string" +Variable="Some string" # But not like this: -VARIABLE = "Some string" -# Bash will decide that VARIABLE is a command it must execute and give an error +Variable = "Some string" +# Bash will decide that Variable is a command it must execute and give an error # because it can't be found. # Or like this: -VARIABLE= 'Some string' +Variable= 'Some string' # Bash will decide that 'Some string' is a command it must execute and give an -# error because it can't be found. (In this case the 'VARIABLE=' part is seen +# error because it can't be found. (In this case the 'Variable=' part is seen # as a variable assignment valid only for the scope of the 'Some string' # command.) # Using the variable: -echo $VARIABLE -echo "$VARIABLE" -echo '$VARIABLE' +echo $Variable +echo "$Variable" +echo '$Variable' # When you use the variable itself — assign it, export it, or else — you write # its name without $. If you want to use variable's value, you should use $. # Note that ' (single quote) won't expand the variables! # String substitution in variables -echo ${VARIABLE/Some/A} +echo ${Variable/Some/A} # This will substitute the first occurance of "Some" with "A" # Substring from a variable -LENGTH=7 -echo ${VARIABLE:0:LENGTH} +Length=7 +echo ${Variable:0:Length} # This will return only the first 7 characters of the value # Default value for variable -echo ${FOO:-"DefaultValueIfFOOIsMissingOrEmpty"} -# This works for null (FOO=) and empty string (FOO=""); zero (FOO=0) returns 0. +echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"} +# This works for null (Foo=) and empty string (Foo=""); zero (Foo=0) returns 0. # Note that it only returns default value and doesn't change variable value. # Builtin variables: @@ -78,12 +78,12 @@ echo "Scripts arguments seperated in different variables: $1 $2..." # Reading a value from input: echo "What's your name?" -read NAME # Note that we didn't need to declare a new variable -echo Hello, $NAME! +read Name # Note that we didn't need to declare a new variable +echo Hello, $Name! # We have the usual if structure: # use 'man test' for more info about conditionals -if [ $NAME -ne $USER ] +if [ $Name -ne $USER ] then echo "Your name isn't your username" else @@ -95,14 +95,14 @@ echo "Always executed" || echo "Only executed if first command fails" echo "Always executed" && echo "Only executed if first command does NOT fail" # To use && and || with if statements, you need multiple pairs of square brackets: -if [ $NAME == "Steve" ] && [ $AGE -eq 15 ] +if [ $Name == "Steve" ] && [ $Age -eq 15 ] then - echo "This will run if $NAME is Steve AND $AGE is 15." + echo "This will run if $Name is Steve AND $Age is 15." fi -if [ $NAME == "Daniya" ] || [ $NAME == "Zach" ] +if [ $Name == "Daniya" ] || [ $Name == "Zach" ] then - echo "This will run if $NAME is Daniya OR Zach." + echo "This will run if $Name is Daniya OR Zach." fi # Expressions are denoted with the following format: @@ -144,7 +144,7 @@ python hello.py > /dev/null 2>&1 # if you want to append instead, use ">>": python hello.py >> "output.out" 2>> "error.err" -# Overwrite output.txt, append to error.err, and count lines: +# Overwrite output.out, append to error.err, and count lines: info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err wc -l output.out error.err @@ -152,7 +152,7 @@ wc -l output.out error.err # see: man fd echo <(echo "#helloworld") -# Overwrite output.txt with "#helloworld": +# Overwrite output.out with "#helloworld": cat > output.out <(echo "#helloworld") echo "#helloworld" > output.out echo "#helloworld" | cat > output.out @@ -171,7 +171,7 @@ echo "There are $(ls | wc -l) items here." echo "There are `ls | wc -l` items here." # Bash uses a case statement that works similarly to switch in Java and C++: -case "$VARIABLE" in +case "$Variable" in #List patterns for the conditions you want to meet 0) echo "There is a zero.";; 1) echo "There is a one.";; @@ -179,10 +179,10 @@ case "$VARIABLE" in esac # for loops iterate for as many arguments given: -# The contents of $VARIABLE is printed three times. -for VARIABLE in {1..3} +# The contents of $Variable is printed three times. +for Variable in {1..3} do - echo "$VARIABLE" + echo "$Variable" done # Or write it the "traditional for loop" way: @@ -193,16 +193,16 @@ done # They can also be used to act on files.. # This will run the command 'cat' on file1 and file2 -for VARIABLE in file1 file2 +for Variable in file1 file2 do - cat "$VARIABLE" + cat "$Variable" done # ..or the output from a command # This will cat the output from ls. -for OUTPUT in $(ls) +for Output in $(ls) do - cat "$OUTPUT" + cat "$Output" done # while loop: @@ -230,7 +230,7 @@ bar () } # Calling your function -foo "My name is" $NAME +foo "My name is" $Name # There are a lot of useful commands you should learn: # prints last 10 lines of file.txt diff --git a/c++.html.markdown b/c++.html.markdown index ae93ceba..66d4aeb1 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -433,6 +433,84 @@ int main () { } ///////////////////// +// Templates +///////////////////// + +// Templates in C++ are mostly used for generic programming, though they are +// much more powerful than generics constructs in other languages. It also +// supports explicit and partial specialization, functional-style type classes, +// and also it's Turing-complete. + +// We start with the kind of generic programming you might be familiar with. To +// define a class or function that takes a type parameter: +template<class T> +class Box { + // In this class, T can be used as any other type. + void insert(const T&) { ... } +}; + +// During compilation, the compiler actually generates copies of each template +// with parameters substituted, and so the full definition of the class must be +// present at each invocation. This is why you will see template classes defined +// entirely in header files. + +// To instantiate a template class on the stack: +Box<int> intBox; + +// and you can use it as you would expect: +intBox.insert(123); + +// You can, of course, nest templates: +Box<Box<int> > boxOfBox; +boxOfBox.insert(intBox); + +// Up until C++11, you muse place a space between the two '>'s, otherwise '>>' +// will be parsed as the right shift operator. + +// You will sometimes see +// template<typename T> +// instead. The 'class' keyword and 'typename' keyword are _mostly_ +// interchangeable in this case. For full explanation, see +// http://en.wikipedia.org/wiki/Typename +// (yes, that keyword has its own Wikipedia page). + +// Similarly, a template function: +template<class T> +void barkThreeTimes(const T& input) +{ + input.bark(); + input.bark(); + input.bark(); +} + +// Notice that nothing is specified about the type parameters here. The compiler +// will generate and then type-check every invocation of the template, so the +// above function works with any type 'T' that has a const 'bark' method! + +Dog fluffy; +fluffy.setName("Fluffy") +barkThreeTimes(fluffy); // Prints "Fluffy barks" three times. + +// Template parameters don't have to be classes: +template<int Y> +void printMessage() { + cout << "Learn C++ in " << Y << " minutes!" << endl; +} + +// And you can explicitly specialize templates for more efficient code. Of +// course, most real-world uses of specialization are not as trivial as this. +// Note that you still need to declare the function (or class) as a template +// even if you explicitly specified all parameters. +template<> +void printMessage<10>() { + cout << "Learn C++ faster in only 10 minutes!" << endl; +} + +printMessage<20>(); // Prints "Learn C++ in 20 minutes!" +printMessage<10>(); // Prints "Learn C++ faster in only 10 minutes!" + + +///////////////////// // Exception Handling ///////////////////// @@ -585,6 +663,54 @@ void doSomethingWithAFile(const std::string& filename) // vector (i.e. self-resizing array), hash maps, and so on // all automatically destroy their contents when they fall out of scope. // - Mutexes using lock_guard and unique_lock + + +///////////////////// +// Fun stuff +///////////////////// + +// Aspects of C++ that may be surprising to newcomers (and even some veterans). +// This section is, unfortunately, wildly incomplete; C++ is one of the easiest +// languages with which to shoot yourself in the foot. + +// You can override private methods! +class Foo { + virtual void bar(); +}; +class FooSub : public Foo { + virtual void bar(); // overrides Foo::bar! +}; + + +// 0 == false == NULL (most of the time)! +bool* pt = new bool; +*pt = 0; // Sets the value points by 'pt' to false. +pt = 0; // Sets 'pt' to the null pointer. Both lines compile without warnings. + +// nullptr is supposed to fix some of that issue: +int* pt2 = new int; +*pt2 = nullptr; // Doesn't compile +pt2 = nullptr; // Sets pt2 to null. + +// But somehow 'bool' type is an exception (this is to make `if (ptr)` compile). +*pt = nullptr; // This still compiles, even though '*pt' is a bool! + + +// '=' != '=' != '='! +// Calls Foo::Foo(const Foo&) or some variant copy constructor. +Foo f2; +Foo f1 = f2; + +// Calls Foo::Foo(const Foo&) or variant, but only copies the 'Foo' part of +// 'fooSub'. Any extra members of 'fooSub' are discarded. This sometimes +// horrifying behavior is called "object slicing." +FooSub fooSub; +Foo f1 = fooSub; + +// Calls Foo::operator=(Foo&) or variant. +Foo f1; +f1 = f2; + ``` Futher Reading: diff --git a/it-it/c++-it.html.markdown b/it-it/c++-it.html.markdown new file mode 100644 index 00000000..4f5ac8a2 --- /dev/null +++ b/it-it/c++-it.html.markdown @@ -0,0 +1,720 @@ +--- +language: c++ +filename: learncpp.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] +translators: + - ["Robert Margelli", "http://github.com/sinkswim/"] +lang: it-it +--- + +Il C++ è un linguaggio di programmazione il quale, +[secondo il suo inventore Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), +è stato progettato per + +- essere un "miglior C" +- supportare l'astrazione dei dati +- supportare la programmazione orientata agli oggetti +- supportare la programmazione generica + +Nonostante la sintassi possa risultare più difficile o complessa di linguaggi più recenti, +è usato in maniera vasta poichè viene compilato in istruzioni macchina che possono +essere eseguite direttamente dal processore ed offre un controllo stretto sull'hardware (come il linguaggio C) +ed allo stesso tempo offre caratteristiche ad alto livello come i generici, le eccezioni, e le classi. +Questa combinazione di velocità e funzionalità rende il C++ +uno dei più utilizzati linguaggi di programmazione. + +```c++ +////////////////// +// Confronto con il C +////////////////// + +// Il C++ è _quasi_ un superset del C e con esso condivide la sintassi di base per +// la dichiarazione di variabili, tipi primitivi, e funzioni. + +// Proprio come nel C, l'inizio del programma è una funzione chiamata +// main con un intero come tipo di ritorno, +// Questo valore serve come stato d'uscita del programma. +// Vedi http://it.wikipedia.org/wiki/Valore_di_uscita per maggiori informazioni. +int main(int argc, char** argv) +{ + // Gli argomenti a linea di comando sono passati tramite argc e argv così come + // avviene in C. + // argc indica il numero di argomenti, + // e argv è un array di stringhe in stile-C (char*) + // che rappresenta gli argomenti. + // Il primo argomento è il nome che è stato assegnato al programma. + // argc e argv possono essere omessi se non hai bisogno di argomenti, + // in questa maniera la funzione avrà int main() come firma. + + // Lo stato di uscita 0 indica successo. + return 0; +} + +// Tuttavia, il C++ varia nei seguenti modi: + +// In C++, i caratteri come letterali sono da un byte. +sizeof('c') == 1 + +// In C, i caratteri come letterali sono della stessa dimensione degli interi. +sizeof('c') == sizeof(10) + + +// C++ ha prototipizzazione rigida +void func(); // funziona che non accetta argomenti + +// In C +void func(); // funzione che può accettare un qualsiasi numero di argomenti + +// Usa nullptr invece di NULL in C++ +int* ip = nullptr; + +// Gli header C standard sono disponibili in C++, +// ma sono prefissati con "c" e non hanno il suffisso ".h". +#include <cstdio> + +int main() +{ + printf("Ciao, mondo!\n"); + return 0; +} + +/////////////////////////////// +// Overloading per le funzioni +////////////////////////////// + +// Il C++ supporta l'overloading per le funzioni +// sia dato che ogni funzione accetta parametri diversi. + +void print(char const* myString) +{ + printf("Stringa %s\n", myString); +} + +void print(int myInt) +{ + printf("Il mio int è %d", myInt); +} + +int main() +{ + print("Ciao"); // Viene chiamata void print(const char*) + print(15); // Viene chiamata void print(int) +} + +//////////////////////// +// Argomenti di default +/////////////////////// + +// Puoi fornire argomenti di default per una funzione +// se non sono forniti dal chiamante. + +void faiQualcosaConInteri(int a = 1, int b = 4) +{ + // fai qualcosa con gli interi qui +} + +int main() +{ + faiQualcosaConInteri(); // a = 1, b = 4 + faiQualcosaConInteri(20); // a = 20, b = 4 + faiQualcosaConInteri(20, 5); // a = 20, b = 5 +} + +// Gli argomenti di default devono essere alla fine della lista degli argomenti. + +void dichiarazioneInvalida(int a = 1, int b) // Errore! +{ +} + + +///////////// +// Namespaces +///////////// + +// I namespaces forniscono visibilità separata per dichiarazioni di variabili, funzioni, +// ed altro. +// I namespaces possono essere annidati. + +namespace Primo { + namespace Annidato { + void foo() + { + printf("Questa è Primo::Annidato::foo\n"); + } + } // fine di namespace Annidato +} // fine di namespace Primo + +namespace Secondo { + void foo() + { + printf("Questa è Secondo::foo\n") + } +} + +void foo() +{ + printf("Questa è foo globale\n"); +} + +int main() +{ + // Assume che tutto venga dal namespace "Secondo" + // a meno che non venga dichiarato altrimenti. + using namespace Secondo; + + foo(); // stampa "Questa è Secondo::foo" + Primo::Annidato::foo(); // stampa "Questa è Primo::Annidato::foo" + ::foo(); // stampa "Questa è foo globale" +} + +/////////////// +// Input/Output +/////////////// + +// L'input e l'output in C++ utilizza gli streams +// cin, cout, e cerr i quali rappresentano stdin, stdout, e stderr. +// << è l'operatore di inserzione >> è l'operatore di estrazione. + +#include <iostream> // Include gli streams di I/O + +using namespace std; // Gli streams sono nel namespace std (libreria standard) + +int main() +{ + int myInt; + + // Stampa su stdout (o terminalee/schermo) + cout << "Inserisci il tuo numero preferito:\n"; + // Prende l'input + cin >> myInt; + + // cout può anche essere formattato + cout << "Il tuo numero preferito è " << myInt << "\n"; + // stampa "Il tuo numero preferito è <myInt>" + + cerr << "Usato per messaggi di errore"; +} + +//////////// +// Stringhe +/////////// + +// Le stringhe in C++ sono oggetti ed hanno molte funzioni membro +#include <string> + +using namespace std; // Anche le stringhe sono contenute nel namespace std (libreria standard) + +string myString = "Ciao"; +string myOtherString = " Mondo"; + +// + è usato per la concatenazione. +cout << myString + myOtherString; // "Ciao Mondo" + +cout << myString + " Bella"; // "Ciao Bella" + +// le stringhe in C++ possono essere modificate. +myString.append(" Mario"); +cout << myString; // "Ciao Mario" + + +/////////////// +// Riferimenti +////////////// + +// Oltre ai puntatori come quelli in C, +// il C++ ha i _riferimenti_. +// Questi non sono tipi puntatori che non possono essere riassegnati una volta settati +// e non possono essere null. +// Inoltre, essi hanno la stessa sintassi della variabile stessa: +// * non è necessario per la dereferenziazione e +// & ("indirizzo di") non è usato per l'assegnamento. + +using namespace std; + +string foo = "Io sono foo"; +string bar = "Io sono bar"; + + +string& fooRef = foo; // Questo crea un riferimento a foo. +fooRef += ". Ciao!"; // Modifica foo attraverso il riferimento +cout << fooRef; // Stampa "Io sono foo. Ciao!" + +// Non riassegna "fooRef". Questo è come scrivere "foo = bar", e +// foo == "Io sono bar" +// dopo questa riga. +fooRef = bar; + +const string& barRef = bar; // Crea un riferimento const a bar. +// Come in C, i valori const (i puntatori e i riferimenti) non possono essere modificati. +barRef += ". Ciao!"; // Errore, i riferimenti const non possono essere modificati. + +////////////////////////////////////////////////// +// Classi e programmazione orientata agli oggetti +///////////////////////////////////////////////// + +// Primo esempio delle classi +#include <iostream> + +// Dichiara una classe. +// Le classi sono in genere dichiara in un header file (.h o .hpp). +class Cane { + // Variabili e funzioni membro sono private di default. + std::string nome; + int peso; + +// Tutti i membri dopo questo sono pubblici (public) +// finchè "private:" o "protected:" non compaiono. +public: + + // Costruttore di default + Cane(); + + // Dichiarazioni di funzioni membro (le implentazioni sono a seguito) + // Nota che stiamo usando std::string invece di porre + // using namespace std; + // sopra. + // Mai usare uno statement "using namespace" in uno header. + void impostaNome(const std::string& nomeCane); + + void impostaPeso(int pesoCane); + + // Le funzioni che non modificano lo stato dell'oggetto + // dovrebbero essere marcate come const. + // Questo permette di chiamarle con un riferimento const all'oggetto. + // Inoltre, nota che le funzioni devono essere dichiarate espliciamente come _virtual_ + // per essere sovrascritte in classi derivate. + // Le funzioni non sono virtual di default per motivi di performance. + virtual void print() const; + + // Le funzioni possono essere definite anche all'interno del corpo della classe. + // Le funzioni definite in questo modo sono automaticamente inline. + void abbaia() const { std::cout << nome << " abbaia!\n"; } + + // Assieme con i costruttori, il C++ fornisce i distruttori. + // Questi sono chiamati quando un oggetto è rimosso o esce dalla visibilità. + // Questo permette paradigmi potenti come il RAII + // (vedi sotto) + // I distruttori devono essere virtual per permettere a classi di essere derivate da questa. + virtual ~Dog(); + +}; // Un punto e virgola deve seguire la definizione della funzione + +// Le funzioni membro di una classe sono generalmente implementate in files .cpp . +void Cane::Cane() +{ + std::cout << "Un cane è stato costruito\n"; +} + +// Gli oggetti (ad esempio le stringhe) devono essere passati per riferimento +// se li stai modificando o come riferimento const altrimenti. +void Cane::impostaNome(const std::string& nomeCane) +{ + nome = nomeCane; +} + +void Cane::impostaPeso(int pesoCane) +{ + peso = pesoCane; +} + +// Notare che "virtual" è solamente necessario nelle dichiarazioni, non nelle definizioni. +void Cane::print() const +{ + std::cout << "Il cane è " << nome << " e pesa " << peso << "kg\n"; +} + +void Cane::~Cane() +{ + cout << "Ciao ciao " << nome << "\n"; +} + +int main() { + Cane myDog; // stampa "Un cane è stato costruito" + myDog.impostaNome("Barkley"); + myDog.impostaPeso(10); + myDog.print(); // stampa "Il cane è Barkley e pesa 10 kg" + return 0; +} // stampa "Ciao ciao Barkley" + +// Ereditarietà: + +// Questa classe eredita tutto ciò che è public e protected dalla classe Cane +class MioCane : public Cane { + + void impostaProprietario(const std::string& proprietarioCane) + + // Sovrascrivi il comportamento della funzione print per tutti i MioCane. Vedi + // http://it.wikipedia.org/wiki/Polimorfismo_%28informatica%29 + // per una introduzione più generale se non sei familiare con + // il polimorfismo. + // La parola chiave override è opzionale ma fa sì che tu stia effettivamente + // sovrascrivendo il metodo nella classe base. + void print() const override; + +private: + std::string proprietario; +}; + +// Nel frattempo, nel file .cpp corrispondente: + +void MioCane::impostaProprietario(const std::string& proprietarioCane) +{ + proprietario = proprietarioCane; +} + +void MioCane::print() const +{ + Cane::print(); // Chiama la funzione print nella classe base Cane + std::cout << "Il cane è di " << proprietario << "\n"; + // stampa "Il cane è <nome> e pesa <peso>" + // "Il cane è di <proprietario>" +} + +/////////////////////////////////////////////////// +// Inizializzazione ed Overloading degli Operatori +////////////////////////////////////////////////// + +// In C++ puoi sovrascrivere il comportamento di operatori come +, -, *, /, ecc... +// Questo è possibile definendo una funzione che viene chiamata +// ogniqualvolta l'operatore è usato. + +#include <iostream> +using namespace std; + +class Punto { +public: + // Così si assegna alle variabili membro un valore di default. + double x = 0; + double y = 0; + + // Definisce un costruttore di default che non fa nulla + // ma inizializza il Punto ai valori di default (0, 0) + Punto() { }; + + // La sintassi seguente è nota come lista di inizializzazione + // ed è il modo appropriato di inizializzare i valori membro della classe + Punto (double a, double b) : + x(a), + y(b) + { /* Non fa nulla eccetto inizializzare i valori */ } + + // Sovrascrivi l'operatore +. + Punto operator+(const Punto& rhs) const; + + // Sovrascrivi l'operatore += + Punto& operator+=(const Punto& rhs); + + // Avrebbe senso aggiungere gli operatori - e -=, + // ma li saltiamo per rendere la guida più breve. +}; + +Punto Punto::operator+(const Punto& rhs) const +{ + // Crea un nuovo punto come somma di questo e di rhs. + return Punto(x + rhs.x, y + rhs.y); +} + +Punto& Punto::operator+=(const Punto& rhs) +{ + x += rhs.x; + y += rhs.y; + return *this; +} + +int main () { + Punto su (0,1); + Punto destro (1,0); + // Questo chiama l'operatore + di Punto + // Il Punto su chiama la funzione + con destro come argomento + Punto risultato = su + destro; + // Stampa "Risultato è spostato in (1,1)" + cout << "Risultato è spostato (" << risultato.x << ',' << risultato.y << ")\n"; + return 0; +} + +///////////////// +// Templates +//////////////// + +// Generalmente i templates in C++ sono utilizzati per programmazione generica, anche se +// sono molto più potenti dei costrutti generici in altri linguaggi. Inoltre, +// supportano specializzazione esplicita e parziale, classi in stile funzionale, +// e sono anche complete per Turing. + +// Iniziamo con il tipo di programmazione generica con cui forse sei familiare. Per +// definire una classe o una funzione che prende un parametro di un dato tipo: +template<class T> +class Box { + // In questa classe, T può essere usato come qualsiasi tipo. + void inserisci(const T&) { ... } +}; + +// Durante la compilazione, il compilatore in effetti genera copie di ogni template +// con i parametri sostituiti, e così la definizione completa della classe deve essere +// presente ad ogni invocazione. Questo è il motivo per cui vedrai le classi template definite +// interamente in header files. + +// Per instanziare una classe template sullo stack: +Box<int> intBox; + +// e puoi usarla come aspettato: +intBox.inserisci(123); + +//Puoi, ovviamente, innestare i templates: +Box<Box<int> > boxOfBox; +boxOfBox.inserisci(intBox); + +// Fino al C++11, devi porre uno spazio tra le due '>', altrimenti '>>' +// viene visto come l'operatore di shift destro. + +// Qualche volta vedrai +// template<typename T> +// invece. La parole chiavi 'class' e 'typename' sono _generalmente_ +// intercambiabili in questo caso. Per una spiegazione completa, vedi +// http://en.wikipedia.org/wiki/Typename +// (si, quella parola chiave ha una sua pagina di Wikipedia propria). + +// Similmente, una funzione template: +template<class T> +void abbaiaTreVolte(const T& input) +{ + input.abbaia(); + input.abbaia(); + input.abbaia(); +} + +// Nota che niente è specificato relativamente al tipo di parametri. Il compilatore +// genererà e poi verificherà il tipo di ogni invocazione del template, così che +// la funzione di cui sopra funzione con ogni tipo 'T' che ha const 'abbaia' come metodo! + +Cane fluffy; +fluffy.impostaNome("Fluffy") +abbaiaTreVolte(fluffy); // Stampa "Fluffy abbaia" tre volte. + +// I parametri template non devono essere classi: +template<int Y> +void stampaMessaggio() { + cout << "Impara il C++ in " << Y << " minuti!" << endl; +} + +// E poi esplicitamente specializzare i template per avere codice più efficiente. Ovviamente, +// la maggior parte delle casistiche reali non sono così triviali. +// Notare che avrai comunque bisogna di dichiarare la funzione (o classe) come un template +// anche se hai esplicitamente specificato tutti i parametri. +template<> +void stampaMessaggio<10>() { + cout << "Impara il C++ più velocemente in soli 10 minuti!" << endl; +} + +printMessage<20>(); // Stampa "impara il C++ in 20 minuti!" +printMessage<10>(); // Stampa "Impara il C++ più velocemente in soli 10 minuti!" + +//////////////////////////// +// Gestione delle eccezioni +/////////////////////////// + +// La libreria standard fornisce un paio di tipi d'eccezioni +// (vedi http://en.cppreference.com/w/cpp/error/exception) +// ma ogni tipo può essere lanciato come eccezione +#include <exception> + +// Tutte le eccezioni lanciate all'interno del blocco _try_ possono essere catturate dai successivi +// handlers _catch_. +try { + // Non allocare eccezioni nello heap usando _new_. + throw std::exception("È avvenuto un problema"); +} +// Cattura le eccezioni come riferimenti const se sono oggetti +catch (const std::exception& ex) +{ + std::cout << ex.what(); +// Cattura ogni eccezioni non catturata dal blocco _catch_ precedente +} catch (...) +{ + std::cout << "Catturata un'eccezione sconosciuta"; + throw; // Rilancia l'eccezione +} + +/////// +// RAII +/////// + +// RAII sta per Resource Allocation Is Initialization. +// Spesso viene considerato come il più potente paradigma in C++. +// È un concetto semplice: un costruttore di un oggetto +// acquisisce le risorse di tale oggetto ed il distruttore le rilascia. + +// Per comprendere come questo sia vantaggioso, +// consideriamo una funzione che usa un gestore di file in C: +void faiQualcosaConUnFile(const char* nomefile) +{ + // Per cominciare, assumiamo che niente possa fallire. + + FILE* fh = fopen(nomefile, "r"); // Apri il file in modalità lettura. + + faiQualcosaConIlFile(fh); + faiQualcosAltroConEsso(fh); + + fclose(fh); // Chiudi il gestore di file. +} + +// Sfortunatamente, le cose vengono complicate dalla gestione degli errori. +// Supponiamo che fopen fallisca, e che faiQualcosaConUnFile e +// faiQualcosAltroConEsso ritornano codici d'errore se falliscono. +// (Le eccezioni sono la maniera preferita per gestire i fallimenti, +// ma alcuni programmatori, specialmente quelli con un passato in C, +// non sono d'accordo con l'utilità delle eccezioni). +// Adesso dobbiamo verificare che ogni chiamata per eventuali fallimenti e chiudere il gestore di file +// se un problema è avvenuto. +bool faiQualcosaConUnFile(const char* nomefile) +{ + FILE* fh = fopen(nomefile, "r"); // Apre il file in modalità lettura + if (fh == nullptr) // Il puntatore restituito è null in caso di fallimento. + return false; // Riporta il fallimento al chiamante. + + // Assumiamo che ogni funzione ritorni false se ha fallito + if (!faiQualcosaConIlFile(fh)) { + fclose(fh); // Chiude il gestore di file così che non sprechi memoria. + return false; // Propaga l'errore. + } + if (!faiQualcosAltroConEsso(fh)) { + fclose(fh); // Chiude il gestore di file così che non sprechi memoria. + return false; // Propaga l'errore. + } + + fclose(fh); // Chiudi il gestore di file così che non sprechi memoria. + return true; // Indica successo +} + +// I programmatori C in genere puliscono questa procedura usando goto: +bool faiQualcosaConUnFile(const char* nomefile) +{ + FILE* fh = fopen(nomefile, "r"); + if (fh == nullptr) + return false; + + if (!faiQualcosaConIlFile(fh)) + goto fallimento; + + if (!faiQualcosAltroConEsso(fh)) + goto fallimento; + + fclose(fh); // Chiude il file + return true; // Indica successo + +fallimento: + fclose(fh); + return false; // Propaga l'errore +} + +// Se le funzioni indicano errori usando le eccezioni, +// le cose sono un pò più pulite, ma sono sempre sub-ottimali. +void faiQualcosaConUnFile(const char* nomefile) +{ + FILE* fh = fopen(nomefile, "r"); // Apre il file in modalità lettura + if (fh == nullptr) + throw std::exception("Non è stato possibile aprire il file."). + + try { + faiQualcosaConIlFile(fh); + faiQualcosAltroConEsso(fh); + } + catch (...) { + fclose(fh); // Fai sì che il file venga chiuso se si ha un errore. + throw; // Poi rilancia l'eccezione. + } + + fclose(fh); // Chiudi il file + // Tutto è andato bene +} + +// Confronta questo con l'utilizzo della classe C++ file stream (fstream) +// fstream usa i distruttori per chiudere il file. +// Come detto sopra, i distruttori sono automaticamente chiamati +// ogniqualvolta un oggetto esce dalla visibilità. +void faiQualcosaConUnFile(const std::string& nomefile) +{ + // ifstream è l'abbreviazione di input file stream + std::ifstream fh(nomefile); // Apre il file + + // Fai qualcosa con il file + faiQualcosaConIlFile(fh); + faiQualcosAltroConEsso(fh); + +} // Il file viene chiuso automaticamente chiuso qui dal distruttore + +// Questo ha vantaggi _enormi_: +// 1. Può succedere di tutto ma +// la risorsa (in questo caso il file handler) verrà ripulito. +// Una volta che scrivi il distruttore correttamente, +// È _impossibile_ scordarsi di chiudere l'handler e sprecare memoria. +// 2. Nota che il codice è molto più pulito. +// Il distruttore gestisce la chiusura del file dietro le scene +// senza che tu debba preoccupartene. +// 3. Il codice è sicuro da eccezioni. +// Una eccezione può essere lanciata in qualunque punto nella funzione e la ripulitura +// avverrà lo stesso. + +// Tutto il codice C++ idiomatico usa RAII in maniera vasta su tutte le risorse. +// Esempi aggiuntivi includono +// - Utilizzo della memoria con unique_ptr e shared_ptr +// - I contenitori - la lista della libreria standard, +// vettori (i.e. array auto-aggiustati), mappe hash, e così via +// sono tutti automaticamente distrutti con i loro contenuti quando escono dalla visibilità. +// - I mutex usano lock_guard e unique_lock + +/////////////////////// +// Roba divertente +////////////////////// + +// Aspetti del C++ che potrebbero sbalordire i nuovi arrivati (e anche qualche veterano). +// Questa sezione è, sfortunatamente, selvaggiamente incompleta; il C++ è uno dei linguaggi +// più facili con cui puoi spararti da solo nel piede. + +// Puoi sovrascrivere metodi privati! +class Foo { + virtual void bar(); +}; +class FooSub : public Foo { + virtual void bar(); // sovrascrive Foo::bar! +}; + + +// 0 == false == NULL (la maggior parte delle volte)! +bool* pt = new bool; +*pt = 0; // Setta il valore puntato da 'pt' come falso. +pt = 0; // Setta 'pt' al puntatore null. Entrambe le righe vengono compilate senza warnings. + +// nullptr dovrebbe risolvere alcune di quei problemi: +int* pt2 = new int; +*pt2 = nullptr; // Non compila +pt2 = nullptr; // Setta pt2 a null. + +// Ma in qualche modo il tipo 'bool' è una eccezione (questo è per rendere compilabile `if (ptr)`. +*pt = nullptr; // Questo compila, anche se '*pt' è un bool! + + +// '=' != '=' != '='! +// Chiama Foo::Foo(const Foo&) o qualche variante del costruttore di copia. +Foo f2; +Foo f1 = f2; + +// Chiama Foo::Foo(const Foo&) o qualche variante, ma solo copie di 'Foo' che fanno parte di +// 'fooSub'. Ogni altro membro di 'fooSub' viene scartato. Questo comportamento +// orribile viene chiamato "object slicing." +FooSub fooSub; +Foo f1 = fooSub; + +// Chiama Foo::operator=(Foo&) o una sua variante. +Foo f1; +f1 = f2; + +``` +Letture consigliate: + +Un riferimento aggiornato del linguaggio può essere trovato qui +<http://cppreference.com/w/cpp> + +Risorse addizionali possono essere trovate qui <http://cplusplus.com> diff --git a/perl6.html.markdown b/perl6.html.markdown index b2d7d48c..3bb87916 100644 --- a/perl6.html.markdown +++ b/perl6.html.markdown @@ -10,8 +10,7 @@ contributors: Perl 6 is a highly capable, feature-rich programming language made for the upcoming hundred years. -Perl 6 runs on [the Parrot VM](http://parrot.org/), the JVM -and [the MoarVM](http://moarvm.com). +Perl 6 runs on [the MoarVM](http://moarvm.com) and the JVM. Meta-note : the triple pound signs are here to denote headlines, double paragraphs, and single notes. @@ -211,7 +210,7 @@ say $x; #=> 52 # - `if` # Before talking about `if`, we need to know which values are "Truthy" # (represent True), and which are "Falsey" (or "Falsy") -- represent False. -# Only these values are Falsey: (), 0, "0", "", Nil, A type (like `Str` or `Int`), +# Only these values are Falsey: (), 0, "", Nil, A type (like `Str` or `Int`), # and of course False itself. # Every other value is Truthy. if True { |