learnxinyminutes-docs/it/c++.md

1134 lines
36 KiB
Markdown
Raw Normal View History

2015-05-06 04:21:53 +00:00
---
2015-06-17 21:25:16 +00:00
filename: learncpp-it.cpp
2015-05-06 04:21:53 +00:00
contributors:
- ["Steven Basart", "http://github.com/xksteven"]
- ["Matt Kline", "https://github.com/mrkline"]
- ["Geoff Liu", "http://geoffliu.me"]
- ["Connor Waters", "http://github.com/connorwaters"]
2015-05-06 04:21:53 +00:00
translators:
- ["Robert Margelli", "http://github.com/sinkswim/"]
Bring this version up to date with the english one (#2503) * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753 * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753
2016-10-24 12:54:58 +00:00
- ["Tommaso Pifferi", "http://github.com/neslinesli93/"]
2015-05-06 04:21:53 +00:00
---
2015-05-06 18:09:31 +00:00
Il C++ è un linguaggio di programmazione il quale,
2015-05-06 04:21:53 +00:00
[secondo il suo inventore Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote),
2015-05-06 18:09:31 +00:00
è stato progettato per
2015-05-06 04:21:53 +00:00
- essere un "miglior C"
- supportare l'astrazione dei dati
- supportare la programmazione orientata agli oggetti
- supportare la programmazione generica
2015-05-06 18:09:31 +00:00
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
2015-05-06 04:21:53 +00:00
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.
2015-05-06 18:09:31 +00:00
Questa combinazione di velocità e funzionalità rende il C++
uno dei più utilizzati linguaggi di programmazione.
2015-05-06 04:21:53 +00:00
```c++
//////////////////
// Confronto con il C
//////////////////
2015-05-06 18:09:31 +00:00
// Il C++ è _quasi_ un superset del C e con esso condivide la sintassi di base per
2015-05-06 04:21:53 +00:00
// la dichiarazione di variabili, tipi primitivi, e funzioni.
2015-05-06 18:09:31 +00:00
// Proprio come nel C, l'inizio del programma è una funzione chiamata
2015-05-06 04:21:53 +00:00
// 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)
{
2015-05-06 18:09:31 +00:00
// Gli argomenti a linea di comando sono passati tramite argc e argv così come
2015-05-06 04:21:53 +00:00
// avviene in C.
// argc indica il numero di argomenti,
2015-05-10 02:18:04 +00:00
// e argv è un array di stringhe in stile-C (char*)
// che rappresenta gli argomenti.
2015-05-06 18:09:31 +00:00
// Il primo argomento è il nome che è stato assegnato al programma.
2015-05-06 04:21:53 +00:00
// argc e argv possono essere omessi se non hai bisogno di argomenti,
2015-05-06 18:09:31 +00:00
// in questa maniera la funzione avrà int main() come firma.
2015-05-06 04:21:53 +00:00
// Lo stato di uscita 0 indica successo.
return 0;
}
// Tuttavia, il C++ varia nei seguenti modi:
// In C++, i caratteri come letterali sono dei char.
sizeof('c') == sizeof(char) == 1
2015-05-06 04:21:53 +00:00
// In C, i caratteri come letterali sono degli interi.
sizeof('c') == sizeof(int)
2015-05-06 04:21:53 +00:00
// C++ ha prototipizzazione rigida
void func(); // funziona che non accetta argomenti
// In C
2015-05-06 18:09:31 +00:00
void func(); // funzione che può accettare un qualsiasi numero di argomenti
2015-05-06 04:21:53 +00:00
// 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)
{
2015-05-06 18:09:31 +00:00
printf("Il mio int è %d", myInt);
2015-05-06 04:21:53 +00:00
}
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
/////////////
2015-05-06 18:09:31 +00:00
// I namespaces forniscono visibilità separata per dichiarazioni di variabili, funzioni,
2015-05-06 04:21:53 +00:00
// ed altro.
// I namespaces possono essere annidati.
namespace Primo {
namespace Annidato {
void foo()
{
2015-05-06 18:09:31 +00:00
printf("Questa è Primo::Annidato::foo\n");
2015-05-06 04:21:53 +00:00
}
} // fine di namespace Annidato
} // fine di namespace Primo
namespace Secondo {
void foo()
{
Bring this version up to date with the english one (#2503) * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753 * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753
2016-10-24 12:54:58 +00:00
printf("Questa è Secondo::foo\n");
2015-05-06 04:21:53 +00:00
}
}
void foo()
{
2015-05-06 18:09:31 +00:00
printf("Questa è foo globale\n");
2015-05-06 04:21:53 +00:00
}
int main()
{
// Include tutti i simboli del namespace Secondo nello scope attuale.
// Osserva che chiamare semplicemente foo() non va più bene perché è ambiguo:
// bisogna specificare se vogliamo chiamare foo definita nel namespace Secondo
// o foo definita nel livello principale del programma.
2015-05-06 04:21:53 +00:00
using namespace Secondo;
Secondo::foo(); // stampa "Questa è Secondo::foo"
2015-05-06 18:09:31 +00:00
Primo::Annidato::foo(); // stampa "Questa è Primo::Annidato::foo"
::foo(); // stampa "Questa è foo globale"
2015-05-06 04:21:53 +00:00
}
///////////////
// Input/Output
///////////////
// L'input e l'output in C++ utilizza gli streams
// cin, cout, e cerr i quali rappresentano stdin, stdout, e stderr.
2015-05-06 18:09:31 +00:00
// << è l'operatore di inserzione >> è l'operatore di estrazione.
2015-05-06 04:21:53 +00:00
2015-05-10 02:18:04 +00:00
#include <iostream> // Include gli streams di I/O
2015-05-06 04:21:53 +00:00
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;
2015-05-06 18:09:31 +00:00
// cout può anche essere formattato
cout << "Il tuo numero preferito è " << myInt << "\n";
// stampa "Il tuo numero preferito è <myInt>"
2015-05-06 04:21:53 +00:00
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";
2015-05-06 18:09:31 +00:00
// + è usato per la concatenazione.
2015-05-06 04:21:53 +00:00
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:
2015-05-06 18:09:31 +00:00
// * non è necessario per la dereferenziazione e
// & ("indirizzo di") non è usato per l'assegnamento.
2015-05-06 04:21:53 +00:00
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!"
2015-05-06 18:09:31 +00:00
// Non riassegna "fooRef". Questo è come scrivere "foo = bar", e
2015-05-06 04:21:53 +00:00
// foo == "Io sono bar"
// dopo questa riga.
cout << &fooRef << endl; // Stampa l'indirizzo di foo
2015-05-06 04:21:53 +00:00
fooRef = bar;
cout << &fooRef << endl; // Stampa lo stesso l'indirizzo di foo
cout << fooRef; // Stampa "Io sono bar"
// L'indirizzo di fooRef rimane lo stesso, ovvero si riferisce ancora a foo.
2015-05-06 04:21:53 +00:00
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.
// Facciamo un piccolo excursus: prima di approfondire ancora i riferimenti, è necessario
// introdurre il concetto di oggetto temporaneo. Supponiamo di avere il seguente codice:
string tempObjectFun() { ... }
string retVal = tempObjectFun();
// Nella seconda riga si ha che:
// - un oggetto di tipo stringa viene ritornato da tempObjectFun
// - viene costruita una nuova stringa, utilizzando l'oggetto ritornato come
// argomento per il costruttore
// - l'oggetto ritornato da tempObjectFun viene distrutto
// L'oggetto ritornato da tempObjectFun viene detto oggetto temporaneo.
// Un oggetto temporaneo viene creato quando una funzione ritorna un oggetto, e viene
// distrutto quando l'espressione che lo racchiude termina la sua esecuzione - questo
// comportamento viene definito dallo standard, ma i compilatori possono modificarlo
// a piacere. Cerca su google "return value optimization" se vuoi approfondire.
// Dunque nel seguente codice:
foo(bar(tempObjectFun()))
// dando per scontato che foo e bar esistano, l'oggetto ritornato da tempObjectFun
// è passato a bar ed è distrutto prima dell'invocazione di foo.
// Tornando ai riferimenti, c'è un'eccezione a quanto appena detto.
// Infatti un oggetto temporaneo "viene distrutto quando l'espressione
// che lo racchiude termina la sua esecuzione", tranne quando è legato ad un
// riferimento di tipo const. In tal caso la sua vita viene estesa per tutto
// lo scope attuale:
void constReferenceTempObjectFun() {
// constRef riceve l'oggetto temporaneo, che non viene distrutto fino
// alla fine di questa funzione.
const string& constRef = tempObjectFun();
...
}
// Un altro tipo di riferimento introdotto nel C++11 è specifico per gli
// oggetti temporanei. Non puoi dichiarare una variabile di quel tipo, ma
// ha la precedenza nella risoluzione degli overload:
void someFun(string& s) { ... } // Riferimento normale
void someFun(string&& s) { ... } // Riferimento ad un oggetto temporaneo
string foo;
someFun(foo); // Chiama la versione con il riferimento normale
someFun(tempObjectFun()); // Chiama la versione con il riferimento temporaneo
// Ad esempio potrai vedere questi due costruttori per std::basic_string:
basic_string(const basic_string& other);
basic_string(basic_string&& other);
// L'idea è che se noi costruiamo una nuova stringa a partire da un oggetto temporaneo
// (che in ogni caso verrà distrutto), possiamo avere un costruttore più efficiente
// che in un certo senso "recupera" parti di quella stringa temporanea.
// Ci si riferisce a questo concetto come "move semantics".
/////////////////////
// Enum
/////////////////////
// Gli enum sono un modo per assegnare un valore ad una costante, e sono
// principalmente usati per rendere il codice più leggibile.
enum ETipiMacchine
{
AlfaRomeo,
Ferrari,
SUV,
Panda
};
ETipiMacchine GetPreferredCarType()
{
return ETipiMacchine::Ferrari;
}
// Dal C++11 in poi c'è un modo molto semplice per assegnare un tipo ad un enum,
// che può essere utile per la serializzazione dei dati o per convertire gli enum
// tra il tipo desiderato e le rispettive costanti.
enum ETipiMacchine : uint8_t
{
AlfaRomeo, // 0
Ferrari, // 1
SUV = 254, // 254
Ibrida // 255
};
void WriteByteToFile(uint8_t InputValue)
{
// Serializza InputValue in un file
}
void WritePreferredCarTypeToFile(ETipiMacchine InputCarType)
{
// L'enum viene implicitamente convertito ad un uint8_t poiché
// è stato dichiarato come tale
WriteByteToFile(InputCarType);
}
// D'altro canto potresti voler evitare che un enum venga accidentalmente convertito
// in un intero o in un altro tipo, quindi è possibile create una classe enum che
// impedisce la conversione implicita.
enum class ETipiMacchine : uint8_t
{
AlfaRomeo, // 0
Ferrari, // 1
SUV = 254, // 254
Ibrida // 255
};
void WriteByteToFile(uint8_t InputValue)
{
// Serializza InputValue in un file
}
void WritePreferredCarTypeToFile(ETipiMacchine InputCarType)
{
// Il compilatore darà errore anche se ETipiMacchine è un uint8_t: questo
// perchè abbiamo dichiarato l'enum come "enum class"!
WriteByteToFile(InputCarType);
}
2015-05-06 04:21:53 +00:00
//////////////////////////////////////////////////
// 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)
2015-05-06 18:09:31 +00:00
// finchè "private:" o "protected:" non compaiono.
2015-05-06 04:21:53 +00:00
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.
2015-05-06 18:09:31 +00:00
// Questi sono chiamati quando un oggetto è rimosso o esce dalla visibilità.
2015-05-06 04:21:53 +00:00
// Questo permette paradigmi potenti come il RAII
// (vedi sotto)
// I distruttori devono essere virtual per permettere a classi di essere
// derivate da questa; altrimenti, il distruttore della classe derivata
// non viene chiamato se l'oggetto viene distrutto tramite un riferimento alla
// classe da cui ha ereditato o tramite un puntatore.
2015-05-06 04:21:53 +00:00
virtual ~Dog();
}; // Un punto e virgola deve seguire la definizione della funzione
2015-05-06 18:09:31 +00:00
// Le funzioni membro di una classe sono generalmente implementate in files .cpp .
Cane::Cane()
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
std::cout << "Un cane è stato costruito\n";
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
// 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)
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
nome = nomeCane;
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
void Cane::impostaPeso(int pesoCane)
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
peso = pesoCane;
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
// Notare che "virtual" è solamente necessario nelle dichiarazioni, non nelle definizioni.
void Cane::print() const
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
std::cout << "Il cane è " << nome << " e pesa " << peso << "kg\n";
2015-05-06 04:21:53 +00:00
}
Cane::~Cane()
2015-05-06 04:21:53 +00:00
{
std::cout << "Ciao ciao " << nome << "\n";
2015-05-06 04:21:53 +00:00
}
int main() {
2015-05-06 18:09:31 +00:00
Cane myDog; // stampa "Un cane è stato costruito"
myDog.impostaNome("Barkley");
myDog.impostaPeso(10);
myDog.print(); // stampa "Il cane è Barkley e pesa 10 kg"
2015-05-06 04:21:53 +00:00
return 0;
2015-05-06 18:09:31 +00:00
} // stampa "Ciao ciao Barkley"
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
// Ereditarietà:
2015-05-06 04:21:53 +00:00
// Questa classe eredita tutto ciò che è public e protected dalla classe Cane,
// ma anche ciò che privato: tuttavia non potrà accedere direttamente a membri/metodi
// privati se non c'è un metodo pubblico o privato che permetta di farlo.
2015-05-06 18:09:31 +00:00
class MioCane : public Cane {
2015-05-06 04:21:53 +00:00
void impostaProprietario(const std::string& proprietarioCane);
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
// 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.
2015-05-06 04:21:53 +00:00
void print() const override;
private:
2015-05-06 18:09:31 +00:00
std::string proprietario;
2015-05-06 04:21:53 +00:00
};
2015-05-06 18:09:31 +00:00
// Nel frattempo, nel file .cpp corrispondente:
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
void MioCane::impostaProprietario(const std::string& proprietarioCane)
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
proprietario = proprietarioCane;
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
void MioCane::print() const
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
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>"
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
///////////////////////////////////////////////////
// Inizializzazione ed Overloading degli Operatori
//////////////////////////////////////////////////
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
// In C++ puoi sovrascrivere il comportamento di operatori come +, -, *, /, ecc...
2015-05-10 02:18:04 +00:00
// Questo è possibile definendo una funzione che viene chiamata
2015-05-06 18:09:31 +00:00
// ogniqualvolta l'operatore è usato.
2015-05-06 04:21:53 +00:00
#include <iostream>
using namespace std;
2015-05-06 18:09:31 +00:00
class Punto {
2015-05-06 04:21:53 +00:00
public:
2015-05-06 18:09:31 +00:00
// Così si assegna alle variabili membro un valore di default.
2015-05-06 04:21:53 +00:00
double x = 0;
double y = 0;
2015-05-06 18:09:31 +00:00
// Definisce un costruttore di default che non fa nulla
// ma inizializza il Punto ai valori di default (0, 0)
Punto() { };
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
// La sintassi seguente è nota come lista di inizializzazione
// ed è il modo appropriato di inizializzare i valori membro della classe
Punto (double a, double b) :
2015-05-06 04:21:53 +00:00
x(a),
y(b)
2015-05-06 18:09:31 +00:00
{ /* Non fa nulla eccetto inizializzare i valori */ }
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
// Sovrascrivi l'operatore +.
Punto operator+(const Punto& rhs) const;
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
// Sovrascrivi l'operatore +=
Punto& operator+=(const Punto& rhs);
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
// Avrebbe senso aggiungere gli operatori - e -=,
// ma li saltiamo per rendere la guida più breve.
2015-05-06 04:21:53 +00:00
};
2015-05-06 18:09:31 +00:00
Punto Punto::operator+(const Punto& rhs) const
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
// Crea un nuovo punto come somma di questo e di rhs.
return Punto(x + rhs.x, y + rhs.y);
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
Punto& Punto::operator+=(const Punto& rhs)
2015-05-06 04:21:53 +00:00
{
x += rhs.x;
y += rhs.y;
return *this;
}
int main () {
2015-05-06 18:09:31 +00:00
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";
2015-05-06 04:21:53 +00:00
return 0;
}
2015-05-09 21:54:19 +00:00
/////////////////
// 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 {
public:
2015-05-09 21:54:19 +00:00
// 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")
2015-05-10 02:18:04 +00:00
abbaiaTreVolte(fluffy); // Stampa "Fluffy abbaia" tre volte.
2015-05-09 21:54:19 +00:00
// 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!"
2015-05-06 04:21:53 +00:00
////////////////////////////
// Gestione delle eccezioni
///////////////////////////
// La libreria standard fornisce un paio di tipi d'eccezioni
// (vedi http://en.cppreference.com/w/cpp/error/exception)
2015-05-06 18:09:31 +00:00
// ma ogni tipo può essere lanciato come eccezione
2015-05-06 04:21:53 +00:00
#include <exception>
#include <stdexcept>
2015-05-06 04:21:53 +00:00
// Tutte le eccezioni lanciate all'interno del blocco _try_ possono essere catturate dai successivi
2015-05-06 04:21:53 +00:00
// handlers _catch_.
try {
// Non allocare eccezioni nello heap usando _new_.
throw std::runtime_error("C'è stato un problema.");
2015-05-06 04:21:53 +00:00
}
2015-05-06 04:21:53 +00:00
// Cattura le eccezioni come riferimenti const se sono oggetti
catch (const std::exception& ex)
{
std::cout << ex.what();
}
2015-05-06 04:21:53 +00:00
// Cattura ogni eccezioni non catturata dal blocco _catch_ precedente
catch (...)
2015-05-06 04:21:53 +00:00
{
std::cout << "Catturata un'eccezione sconosciuta";
throw; // Rilancia l'eccezione
}
///////
// RAII
///////
// RAII sta per "Resource Allocation Is Initialization".
2015-05-06 18:09:31 +00:00
// Spesso viene considerato come il più potente paradigma in C++.
// È un concetto semplice: un costruttore di un oggetto
2015-05-06 04:21:53 +00:00
// 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.
2015-05-06 18:09:31 +00:00
FILE* fh = fopen(nomefile, "r"); // Apri il file in modalità lettura.
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
faiQualcosaConIlFile(fh);
2015-05-06 04:21:53 +00:00
faiQualcosAltroConEsso(fh);
fclose(fh); // Chiudi il gestore di file.
}
2015-05-06 18:09:31 +00:00
// 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).
2015-05-06 18:09:31 +00:00
// Adesso dobbiamo verificare che ogni chiamata per eventuali fallimenti e chiudere il gestore di file
// se un problema è avvenuto.
bool faiQualcosaConUnFile(const char* nomefile)
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
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.
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
if (!faiQualcosAltroConEsso(fh)) {
fclose(fh); // Chiude il gestore di file così che non sprechi memoria.
return false; // Propaga l'errore.
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
fclose(fh); // Chiudi il gestore di file così che non sprechi memoria.
return true; // Indica successo
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
// I programmatori C in genere puliscono questa procedura usando goto:
bool faiQualcosaConUnFile(const char* nomefile)
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
FILE* fh = fopen(nomefile, "r");
2015-05-06 04:21:53 +00:00
if (fh == nullptr)
return false;
2015-05-06 18:09:31 +00:00
if (!faiQualcosaConIlFile(fh))
goto fallimento;
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
if (!faiQualcosAltroConEsso(fh))
goto fallimento;
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
fclose(fh); // Chiude il file
return true; // Indica successo
2015-05-06 04:21:53 +00:00
2015-05-06 18:09:31 +00:00
fallimento:
2015-05-06 04:21:53 +00:00
fclose(fh);
2015-05-06 18:09:31 +00:00
return false; // Propaga l'errore
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
// 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)
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
FILE* fh = fopen(nomefile, "r"); // Apre il file in modalità lettura
2015-05-06 04:21:53 +00:00
if (fh == nullptr)
throw std::runtime_error("Errore nell'apertura del file.");
2015-05-06 04:21:53 +00:00
try {
2015-05-06 18:09:31 +00:00
faiQualcosaConIlFile(fh);
faiQualcosAltroConEsso(fh);
2015-05-06 04:21:53 +00:00
}
catch (...) {
2015-05-06 18:09:31 +00:00
fclose(fh); // Fai sì che il file venga chiuso se si ha un errore.
throw; // Poi rilancia l'eccezione.
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
fclose(fh); // Chiudi il file
// Tutto è andato bene
2015-05-06 04:21:53 +00:00
}
2015-05-06 18:09:31 +00:00
// 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)
2015-05-06 04:21:53 +00:00
{
2015-05-06 18:09:31 +00:00
// 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
2015-05-09 21:54:19 +00:00
Bring this version up to date with the english one (#2503) * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753 * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753
2016-10-24 12:54:58 +00:00
// I contenitori che utilizzano chiavi non-primitive (classi personalizzate)
// richiedono la funzione di confronto nell'oggetto stesso, o tramite un puntatore a funzione.
// Le chiavi primitive hanno funzioni di confronto già definite, ma puoi sovrascriverle.
class Foo {
public:
int j;
Foo(int a) : j(a) {}
};
struct funzioneDiConfronto {
bool operator()(const Foo& a, const Foo& b) const {
return a.j < b.j;
}
};
// Questo non è permesso, anche se qualche compilatore potrebbe non dare problemi
//std::map<Foo, int> fooMap;
std::map<Foo, int, funzioneDiConfronto> fooMap;
fooMap[Foo(1)] = 1;
fooMap.find(Foo(1)); -- vero
///////////////////////////////////////
// Espressioni Lambda (C++11 e superiori)
///////////////////////////////////////
// Le espressioni lambda (più semplicemente "lambda") sono utilizzate
// per definire una funzione anonima nel punto in cui viene invocata, o
// dove viene passata come argomento ad una funzione
// Ad esempio, consideriamo l'ordinamento di un vettore costituito da una
// coppia di interi, utilizzando il secondo elemento per confrontare
vector<pair<int, int> > tester;
tester.push_back(make_pair(3, 6));
tester.push_back(make_pair(1, 9));
tester.push_back(make_pair(5, 0));
// Passiamo una lambda come terzo argomento alla funzione di ordinamento
// `sort` è contenuta nell'header <algorithm>
sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
return lhs.second < rhs.second;
});
// Nota bene la sintassi utilizzata nelle lambda:
// [] serve per "catturare" le variabili.
// La "Lista di Cattura" definisce tutte le variabili esterne che devono essere disponibili
// all'interno della funzione, e in che modo.
// La lista può contenere:
// 1. un valore: [x]
// 2. un riferimento: [&x]
// 3. qualunque variabile nello scope corrente, per riferimento [&]
// 4. qualunque variabile nello scope corrente, per valore [=]
// Esempio:
vector<int> id_cani;
// numero_cani = 3;
for(int i = 0; i < 3; i++) {
id_cani.push_back(i);
}
int pesi[3] = {30, 50, 10};
// Mettiamo che vuoi ordinare id_cani in base al peso dei cani
// Alla fine, id_cani sarà: [2, 0, 1]
// Le lambda vengono in aiuto
sort(id_cani.begin(), id_cani.end(), [&pesi](const int &lhs, const int &rhs) {
return pesi[lhs] < pesi[rhs];
});
// Nota come abbiamo catturato "pesi" per riferimento nell'esempio.
// Altre informazioni sulle lambda in C++: http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
///////////////////////////////
// Ciclo For semplificato(C++11 e superiori)
///////////////////////////////
// Puoi usare un ciclo for per iterare su un tipo di dato contenitore
int arr[] = {1, 10, 3};
for(int elem: arr) {
cout << elem << endl;
}
// Puoi usare "auto" senza preoccuparti del tipo degli elementi nel contenitore
// Ad esempio:
for(auto elem: arr) {
// Fai qualcosa con `elem`
}
2015-05-09 21:54:19 +00:00
///////////////////////
// Roba divertente
//////////////////////
// Aspetti del C++ che potrebbero sbalordire i nuovi arrivati (e anche qualche veterano).
2015-05-10 02:18:04 +00:00
// Questa sezione è, sfortunatamente, selvaggiamente incompleta; il C++ è uno dei linguaggi
2015-05-09 21:54:19 +00:00
// 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!
2015-05-09 21:54:19 +00:00
};
// 0 == false == NULL (la maggior parte delle volte)!
bool* pt = new bool;
*pt = 0; // Setta il valore puntato da 'pt' come falso.
2015-05-09 21:54:19 +00:00
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
2015-05-09 21:54:19 +00:00
pt2 = nullptr; // Setta pt2 a null.
// C'è un'eccezione per i bool.
// Questo permette di testare un puntatore a null con if(!ptr), ma
// come conseguenza non puoi assegnare nullptr a un bool direttamente!
*pt = nullptr; // Questo compila, anche se '*pt' è un bool!
2015-05-09 21:54:19 +00:00
// '=' != '=' != '='!
// Chiama Foo::Foo(const Foo&) o qualche variante (vedi "move semantics")
// del costruttore di copia.
2015-05-09 21:54:19 +00:00
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;
Bring this version up to date with the english one (#2503) * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753 * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753
2016-10-24 12:54:58 +00:00
///////////////////////////////////////
// Tuple (C++11 e superiori)
///////////////////////////////////////
#include<tuple>
// Concettualmente le tuple sono simili alle strutture del C, ma invece di avere
// i membri rappresentati con dei nomi, l'accesso agli elementi avviene tramite
// il loro ordine all'interno della tupla.
// Cominciamo costruendo una tupla.
// Inserire i valori in una tupla
auto prima = make_tuple(10, 'A');
const int maxN = 1e9;
const int maxL = 15;
auto seconda = make_tuple(maxN, maxL);
// Vediamo gli elementi contenuti nella tupla "prima"
cout << get<0>(prima) << " " << get<1>(prima) << "\n"; // stampa : 10 A
// Vediamo gli elementi contenuti nella tupla "seconda"
cout << get<0>(seconda) << " " << get<1>(seconda) << "\n"; // stampa: 1000000000 15
// Estrarre i valori dalla tupla, salvandoli nelle variabili
int primo_intero;
char primo_char;
tie(primo_intero, primo_char) = prima;
cout << primo_intero << " " << primo_char << "\n"; // stampa : 10 A
// E' possibile creare tuple anche in questo modo
tuple<int, char, double> terza(11, 'A', 3.14141);
// tuple_size ritorna il numero di elementi in una tupla (come constexpr)
cout << tuple_size<decltype(terza)>::value << "\n"; // stampa: 3
// tuple_cat concatena gli elementi di tutte le tuple, nell'esatto ordine
// in cui sono posizionati all'interno delle tuple stesse
auto tupla_concatenata = tuple_cat(prima, seconda, terza);
// tupla_concatenata diventa = (10, 'A', 1e9, 15, 11, 'A' ,3.14141)
cout << get<0>(tupla_concatenata) << "\n"; // stampa: 10
cout << get<3>(tupla_concatenata) << "\n"; // stampa: 15
cout << get<5>(tupla_concatenata) << "\n"; // stampa: 'A'
/////////////////////
// Contenitori
/////////////////////
// I Contenitori della "Standard Template Library", ovvero la libreria standard
// dei template contenuti nel C++, sono template predefiniti.
// I Contenitori si occupano di come allocare lo spazio per gli elementi contenuti,
// e forniscono funzioni per accedervi e manipolarli
// Vediamo alcuni tipi di contenitori:
// Vector (array dinamici/vettori)
// Permettono di definire un vettore, o una lista di oggetti, a runtime
#include<vector>
vector<Tipo_Dato> nome_vettore; // usato per inizializzare un vettore
cin >> val;
nome_vettore.push_back(val); // inserisce il valore di "val" nel vettore
// Per iterare in un vettore, abbiamo due possibilità:
// Ciclo normale
for(int i=0; i<nome_vettore.size(); i++)
// Cicla dall'indice zero fino all'ultimo
// Iteratore
vector<Tipo_Dato>::iterator it; // inizializza l'iteratore per il vettore
for(it=nome_vettore.begin(); it!=nome_vettore.end();++it)
// Nota che adesso non cicla più sugli indici, ma direttamente sugli elementi!
// Per accedere agli elementi del vettore
// Operatore []
var = nome_vettore[indice]; // Assegna a "var" il valore del vettore all'indice dato
// Set (insiemi)
// Gli insiemi sono contenitori che memorizzano elementi secondo uno specifico ordine.
// Gli insiemi vengono per lo più utilizzati per memorizzare valori unici, secondo
// un ordine, senza scrivere ulteriore codice.
#include<set>
set<int> insieme; // Inizializza un insieme di interi
insieme.insert(30); // Inserisce il valore 30 nell'insieme
insieme.insert(10); // Inserisce il valore 10 nell'insieme
insieme.insert(20); // Inserisce il valore 20 nell'insieme
insieme.insert(30); // Inserisce il valore 30 nell'insieme
// Gli elementi dell'insieme sono:
// 10 20 30
// Per cancellare un elemento
insieme.erase(20); // Cancella l'elemento con valore 20
// L'insieme contiene adesso: 10 30
// Per iterare su un insieme, usiamo gli iteratori
set<int>::iterator it;
for(it=insieme.begin();it<insieme.end();it++) {
cout << *it << endl;
}
// Stampa:
// 10
// 30
// Per svuotare il contenitore usiamo il metodo "clear"
insieme.clear();
cout << insieme.size();
// Stampa: 0
// Nota: per permettere elementi duplicati, possiamo usare "multiset"
// Map (mappa/tabella di hash)
// Le mappe servono per memorizzare un elemento, detto chiave, a cui viene
// associato un valore, il tutto secondo uno specifico ordine.
#include<map>
map<char, int> mia_mappa; // Inizializza una mappa che usa i char come chiave, e gli interi come valore
mia_mappa.insert(pair<char,int>('A',1));
// Inserisce il valore 1 per la chiave A
mia_mappa.insert(pair<char,int>('Z',26));
// Inserisce il valore 26 per la chiave Z
// Per iterare
map<char,int>::iterator it;
for (it=mia_mappa.begin(); it!=mia_mappa.end(); ++it)
std::cout << it->first << "->" << it->second << '\n';
// Stampa:
// A->1
// Z->26
// Per trovare il valore corrispondente ad una data chiave
it = mia_mappa.find('Z');
cout << it->second;
// Stampa: 26
///////////////////////////////////
// Operatori logici e bitwise(bit-a-bit)
//////////////////////////////////
// La maggior parte di questi operatori in C++ sono gli stessi degli altri linguaggi
// Operatori logici
// Il C++ usa la "Short-circuit evaluation" per le espressioni booleane. Cosa significa?
// In pratica, in una condizione con due argomenti, il secondo viene considerato solo se
// il primo non basta a determinate il valore finale dell'espresione.
true && false // Effettua il **and logico** e ritorna falso
true || false // Effettua il **or logico** e ritorna vero
! true // Effettua il **not logico** e ritorna falso
// Invece di usare i simboli, si possono usare le keyword equivalenti
true and false // Effettua il **and logico** e ritorna falso
true or false // Effettua il **or logico** e ritorna vero
not true // Effettua il **not logico** e ritorna falso
// Operatori bitwise(bit-a-bit)
// **<<** Operatore di Shift a Sinistra
// << sposta i bit a sinistra
4 << 1 // Sposta a sinistra di 1 i bit di 4, ottenendo 8
// x << n in pratica realizza x * 2^n
// **>>** Operatore di Shift a Destra
// >> sposta i bit a destra
4 >> 1 // Sposta a destra di 1 i bit di 4, ottenendo 2
// x >> n in pratica realizza x / 2^n
Bring this version up to date with the english one (#2503) * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753 * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753
2016-10-24 12:54:58 +00:00
~4 // Effettua il NOT bit-a-bit
4 | 3 // Effettua il OR bit-a-bit
4 & 3 // Effettua il AND bit-a-bit
4 ^ 3 // Effettua il XOR bit-a-bit
Bring this version up to date with the english one (#2503) * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753 * Bring this version up to date with the english one The following commits were taken into consideration and translated into italian: c3e769e4ac50d4475a530969663e073f4ff002ca fd26c8ddfb6d4bfa969b323a2e98ce1b74bc8127 19ead59c1fde3623bc29e1fe56f33f2587c97d3a e6866f5a26dab28d2d1b5628fbb18139c36a5139 32f18cd992b5b6988a3b37eaa533f8215d83fe2e c805148618f5b2679d6581ff41885abc7140fd4d 4a1a6857ce30f19f8c04dcca4571bb27f7dc36d0 fa2b171008061bc82cf9b35e0470eebeaecb4a26 e1016455d5e4472e7a533c8cdd6df8ae4f2e7854 1bb2535efda67de687d4eb94a0f964f9c06dcd4a 1d562740f3d3b68fbb51a45f66ae6b60eee7b2de 281ba5b37a9e4e42d33442b0d3a062d99c964a95 c50ff9299651ba3c856ee23cbdabeda2784b864c 47679dfcbe82811b7042a5994baab448adc15dd4 042ed5038101d59a9d438cc2410fd9c91a343753
2016-10-24 12:54:58 +00:00
// Le keyword equivalenti sono
compl 4 // Effettua il NOT bit-a-bit
4 bitor 3 // Effettua il OR bit-a-bit
4 bitand 3 // Effettua il AND bit-a-bit
4 xor 3 // Effettua il XOR bit-a-bit
2015-05-06 04:21:53 +00:00
```
2015-05-06 04:21:53 +00:00
Letture consigliate:
2018-10-14 00:04:24 +00:00
* Un riferimento aggiornato del linguaggio può essere trovato qui [CPP Reference](http://cppreference.com/w/cpp).
* Risorse addizionali possono essere trovate qui [CPlusPlus](http://cplusplus.com).
2018-10-14 00:21:14 +00:00
* Un tutorial che copre le basi del linguaggio e l'impostazione dell'ambiente di codifica è disponibile su [TheChernoProject - C ++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).