6
6
7
7
#include " Alpha.h"
8
8
9
- /*
10
-
11
-
12
- :: è chiamato operatore di risoluzione dello scope
13
- l'overloading (sovraccarico) degli operatori (ridefinizione della loro semantica).
14
- operatori << >> sovraccaricati dalle classi ostream e istream
15
- endl e' un manipolatore, inserisce carattere nl e forza flush
16
- OPERATORI BINARI forme equivalenti:
17
- 1) obj.operator<<(param);
18
- 2) operator<<(obj, param2);
19
-
20
- Lvalue: oggetto con un nome (es. variabili) e un indirizzo di
21
- memoria preciso che posso ottenere con l'operatore &.
22
- Posso passari per riferimento
23
-
24
- Rvalue: valore temporaneo che non esiste più dopo l'espressione che lo usa
25
- int f(int& x) {} f(6); KO, rvalue non accettato
26
- int f(const int& x) {} f(6); OK, const ref
27
- int f(int&& x) {} f(6); OK, rvalue ref
28
-
29
- int x = 7 + 10; // x Lvalue, (17) Rvalue
30
-
31
- In C++03, the compiler provides, for classes that do not provide them for themselves, a default constructor,
32
- a copy constructor, a copy assignment operator (operator=), and a destructor.
33
-
34
-
35
-
36
-
37
- */
38
-
39
9
using namespace std ; // Rende visibili i nomi definiti in questo namespace
40
-
10
+ // namespace xyz = supsi::dti; // alias namespace
41
11
42
12
class Collaboratore {
43
13
string m_nome;
44
- string m_istituto;
45
- int m_nrcollab;
46
14
public:
47
15
Collaboratore () = default ;
48
- Collaboratore (string nome, string istituto, int nr_collab) :
49
- m_nome{nome}, m_istituto{istituto}, m_nrcollab{nr_collab}
50
- {
16
+ Collaboratore (string nome) : m_nome{nome} {
51
17
cout << " Collaboratore Ctor" << endl;
52
18
}
53
19
54
-
55
20
string nome () const { return m_nome; }
56
- string istituto () const { return m_istituto; }
57
- int nrcollab () const { return m_nrcollab; }
58
- string nomeclasse () const { return " Collaboratore" ; }
59
- // virtual string toString()=0; // abstract class
60
- virtual string toString () { return nome () + " , " + istituto (); }
21
+ string classe () const { return " Collaboratore" ; }
22
+ virtual string toString () { return nome (); }
61
23
};
62
24
25
+ // ereditarieta' multipla: uso virtual base class
63
26
class Docente : public virtual Collaboratore {
64
27
string m_corso;
65
28
public:
66
- Docente (string nome, string istituto, int nr_collab, string corso) :
67
- Collaboratore{nome, istituto, nr_collab },
29
+ Docente (string nome, string corso) :
30
+ Collaboratore{nome},
68
31
m_corso{corso}
69
32
{}
70
- string corso () const { return m_corso;}
71
- string nomeclasse () const { return " Docente" ; }
33
+ string corso () const noexcept { return m_corso;}
34
+ string classe () const { return " Docente" ; }
72
35
73
- string toString () override // il compilatore controlla che esista un metodo virtual
74
- { return nomeclasse () + " : " + corso (); }
36
+ // il compilatore controlla che esista un metodo virtual
37
+ string toString () override { return classe () + " : " + corso (); }
75
38
};
76
39
77
-
40
+ // ereditarieta' multipla: uso virtual base class
78
41
class Ricercatore : public virtual Collaboratore {
79
42
string m_arearicerca;
80
43
public:
81
- Ricercatore (string nome, string istituto, int nr_collab, string arearicerca) :
82
- Collaboratore{nome, istituto, nr_collab },
44
+ Ricercatore (string nome, string arearicerca) :
45
+ Collaboratore{nome},
83
46
m_arearicerca{arearicerca}
84
47
{}
85
48
string arearicerca () const {return m_arearicerca; }
86
- string nomeclasse () const { return " Ricercatore" ; }
49
+ string classe () const { return " Ricercatore" ; }
87
50
};
88
51
89
52
// ereditarieta' multipla: uso virtual base class
53
+ // class Ricercatore : public virtual Collaboratore ...
54
+ // class Docente : public virtual Collaboratore ...
90
55
// ora il compilatore usa costruttore vuoto di Collaboratore
91
56
// invece di quello usato nella init-list di Docente e Ricercatore.
92
57
// Quindi il costruttore vuoto va dichiarato esplicito
@@ -95,101 +60,133 @@ class Ricercatore : public virtual Collaboratore {
95
60
class DocenteRicercatore : public Docente , public Ricercatore {
96
61
double m_percRicerca;
97
62
public:
98
- DocenteRicercatore (string nome, string istituto,
99
- int nr_collab, string corso, string arearicerca,
100
- double percRicerca) :
101
- Collaboratore (nome, istituto, nr_collab),
102
- Docente{nome, istituto, nr_collab, corso},
103
- Ricercatore{nome, istituto, nr_collab, arearicerca},
63
+ DocenteRicercatore (string nome, string corso, string arearicerca, double percRicerca) :
64
+ Collaboratore (nome),
65
+ Docente{nome, corso},
66
+ Ricercatore{nome, arearicerca},
104
67
m_percRicerca{percRicerca}
105
68
{}
106
69
double percRicerca () const { return m_percRicerca; }
107
- string nomeclasse () const { return " DocenteRicercatore" ; }
70
+ string classe () const { return " DocenteRicercatore" ; }
108
71
};
109
72
110
-
111
- enum class Sesso { Maschio, Femmina }; // strongly typed, non convertito in num
112
- struct Persona { string nome; }; // typedef non necessario
113
-
114
- void testCast ();
115
-
116
- void testAuto ();
117
-
118
- void ordineCostrDestr ();
119
-
120
- void binding ();
121
-
122
- int moltiplica (int a, int b) noexcept { return a * b; }
123
- namespace supsi {
124
- namespace dti {
125
- int moltiplica (int a, int b) { return ::moltiplica (a, b); }
126
- }}
127
-
128
- void swap (int & x, int & y) {
129
- int temp{x};
130
- x = y;
131
- y = temp;
132
- }
133
-
134
73
/*
135
74
int& sbagliato(int& x, int& y) {
136
75
int temp;
137
76
return temp; // Attenzione! Ritorno un rif. a una variabile locale!!!!
138
77
}*/
139
78
140
- namespace xyz = supsi::dti; // alias namespace
141
79
142
- struct A {
143
- A () { cout << " create A" << endl; }
144
- ~A () { cout << " destr A" << endl; }
145
- string foo () { return " A.foo() " ; }
146
- // VISIBILITA:
147
- // Un metodo con lo stesso nome di un metodo di una classe
148
- // base nasconde tutte le funzioni sovraccaricate con lo stesso
149
- // nome nella classe base
150
- string p (int v) { return " A.p(int) " ; }
151
- string p () { return " A.p() " ; }
80
+ /*
81
+ Rvalue: valore temporaneo (non hanno nome) che non esiste più dopo l'espressione che lo usa
82
+ int f(int& x) {} f(6); KO, rvalue non accettato
83
+ int f(const int& x) {} f(6); OK, const ref
84
+ int f(int&& x) {} f(6); OK, rvalue ref
85
+ */
152
86
87
+ class F {
88
+ public:
89
+ F (int n=0 , int d=1 ) : m_num{n}, m_den{d} {}
90
+
91
+ int num () const { return m_num; } // getter
92
+ void num (int n) { m_num = n; } // setter
93
+ int den () const { return m_den; }
94
+ void den (int d) { m_den = d; }
95
+
96
+ F& operator += (const F& f){
97
+ int temp_numeratore { f.m_num * m_den };
98
+ m_den *= f.m_den ;
99
+ m_num *= f.m_den ;
100
+ m_num += temp_numeratore;
101
+ return *this ;
102
+ };
103
+ F& operator -= (const F& f){
104
+ int temp_numeratore { f.m_num * m_den };
105
+ m_den *= f.m_den ;
106
+ m_num *= f.m_den ;
107
+ m_num -= temp_numeratore;
108
+ return *this ;
109
+ };
110
+ // conversion/cast operator: F f{3,4}; double a=f;
111
+ operator double () { return double (m_num) / m_den; }
112
+ // prefix ++f
113
+ F& operator ++() { return *this += 1 ; }
114
+ // postfix f++ (inserisco un parametro fittizio)
115
+ F operator ++(int ) {
116
+ F old{*this };
117
+ *this += 1 ;
118
+ return old;
119
+ }
120
+
121
+ private:
122
+ int m_num, m_den;
123
+ };
124
+
125
+ // f1 copy, f2 reference. return a copy
126
+ F operator + (F f1, const F& f2) {
127
+ return f1 += f2;
128
+ };
129
+
130
+ // bitshift operator (binario), overload da ostream
131
+ // es. o << f; o.operator<<(f); operator<<(o, f);
132
+ // endl manipolatore, inserisce carattere nl e forza flush
133
+ ostream& operator << (ostream& o, const F& f) {
134
+ o << f.num () << " /" << f.den () << endl;
135
+ return o;
136
+ };
137
+
138
+ // il compilatore automaticamente crea:
139
+ // default ctor (se altri costruttori non esplicitati)
140
+ // copy ctor, copy assignment (operator=), destructor (non ereditati)
141
+ struct A {
142
+ A () : m_num{-1 } { cout << " A()" << endl; }
143
+ // explicit: evita implicit conversion
144
+ explicit A (int val) : m_num{val} { cout << " A(int)" << endl; }
145
+ virtual ~A () { cout << " ~A()" << endl; }
153
146
virtual string f () { return " A.f() " ; }
147
+ string g () { return " A.g() " ; }
148
+ string h () { return " A.h() " ; }
149
+ string h (int v) { return " A.h(int) " ; } // overloading di h()
150
+ private:
151
+ int m_num;
154
152
};
155
153
156
154
struct B : A {
157
- B () { cout << " create B" << endl; }
158
- ~B () { cout << " destr B" << endl; }
159
-
160
- string p (string f) { return " B.p(str) " ; }
155
+ B () { cout << " B()" << endl; }
156
+ B (string str) : A{10 }, m_str{" default" } { cout << " B(str)" ; }
157
+ virtual ~B () { cout << " ~B()" << endl; }
161
158
162
- string foo () { return " B.foo() " ; }
163
- string f () final { return " B.f() " ; }
159
+ string f () override final { return " B.f() " ; } // final method
160
+ string g () { return " B.g() " ; } // HIDING: perche' A::g() non virtual
161
+ string h (string str) { m_str = str; return " B.h(str) " ; }
164
162
165
- using A::p; // risolvo problema di HIDING, alternativa b.A::p(12)
163
+ // HIDING: metodo con stesso nome definito in classe base
164
+ // nasconde tutte i metodi sovraccaricati nella classe base
165
+ // :: è chiamato operatore di risoluzione dello scope
166
+ using A::h; // fix hiding, ora tutti gli h sono visibili
167
+ // alternativa client chiama esplicit b.A::h(12)
166
168
167
- // funzioni mai ereditate, hanno bisogno info su oggetto
168
- // – I costruttori di copia
169
- // – Gli operatori di assegnamento di copia
170
- // – I distruttori
169
+ private:
170
+ string m_str;
171
171
};
172
172
173
- // B e' final: impedisce ulteriori derivazioni
173
+ // C e' final: impedisce ulteriori derivazioni
174
174
struct C final : B {
175
175
// ctor with initializer_list HA PRECEDENZA
176
176
C (const std::initializer_list<int >& valori) {
177
- cout << " C ctor init_list" << endl;
178
- for (const auto & v : valori) {
179
- m_vect.push_back (v);
180
- }
177
+ cout << " C(init_list) " << endl;
178
+ for (const auto & v : valori) { m_vect.push_back (v); }
181
179
}
182
180
183
- C (int sz) {
184
- cout << " C ctor int" << endl;
185
- m_vect.reserve (sz); }
181
+ explicit C (int sz) {
182
+ cout << " C(int)" << endl;
183
+ m_vect.reserve (sz);
184
+ }
186
185
187
186
// string f() {} non posso piu' fare override perche' f e' final in B
188
187
189
188
void print () {
190
- for (const auto & x : m_vect) {
191
- cout << x;
192
- }
189
+ for (const auto & x : m_vect) { cout << x; }
193
190
cout << endl;
194
191
}
195
192
void removeAt (int pos) {
@@ -206,6 +203,14 @@ struct C final : B {
206
203
};
207
204
208
205
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
209
214
void test_std () {
210
215
// String Stream
211
216
stringstream sstr;
@@ -245,9 +250,9 @@ void binding() {
245
250
// vtable all'interno della classe (condivisa tra tutti gli oggetti)
246
251
A a; B b;
247
252
A& ab{b};
248
- cout << " a " << a.foo () << a.f () << a.p () << a.p (12 ) << endl;
249
- cout << " b " << b.foo () << b.f () << b.A ::f () << b.p () << b.p (" c" ) << endl;
250
- cout << " ab " << ab.foo () << ab.f () << endl;
253
+ cout << " a " << a.g () << a.f () << a.h () << a.h (12 ) << endl;
254
+ cout << " b " << b.g () << b.f () << b.A ::f () << b.h () << b.h (" c" ) << endl;
255
+ cout << " ab " << ab.g () << ab.f () << endl;
251
256
}
252
257
253
258
void ordineCostrDestr () {
@@ -279,10 +284,10 @@ void testAuto() {
279
284
// mystr.erase(3,6);
280
285
// mystr.replace(0, 5, "Hello");
281
286
// size_t pos = mystr.find("mondo", 0);
282
- int pi_a = 3.14 ; // Diventa 3!
287
+ // int pi_a = 3.14; // Diventa 3!
283
288
// int pi_b {3.14}; // Problema!
284
289
auto r{1.2 }; // compilatore cambia auto in double
285
- auto k{moltiplica (4 ,2 )}; // compilatore cambia auto in int
290
+ // auto k{moltiplica(4,2)}; // compilatore cambia auto in int
286
291
287
292
int mioarray[] { 1 , 5 , 3 , 6 , 2 };
288
293
for (auto i : mioarray) cout << i << endl;
@@ -312,11 +317,11 @@ void testAuto() {
312
317
}
313
318
314
319
void testCast () {
315
- DocenteRicercatore dr{" Massimo" , " SUPSI " , 123 , " DTI" , " MED" , 12.3 };
320
+ DocenteRicercatore dr{" Massimo" , " DTI" , " MED" , 12.3 };
316
321
cout << dr.nome () << endl;
317
322
cout << typeid (dr).name () << endl; // 18DocenteRicercatore
318
323
319
- Docente doc{" Giovanni" , " ISIN " , 42 , " Linguaggi e framework " };
324
+ Docente doc{" Giovanni" , " Linguaggi" };
320
325
cout << typeid (doc).name () << endl; // 7Docente
321
326
322
327
// static_cast<tipo>(oggetto), check durante compilazione
@@ -390,9 +395,9 @@ void smart_pointers() {
390
395
391
396
vector<unique_ptr<int >> v;
392
397
unique_ptr<int > p {new int {13 }};
393
- // v.push_back(p ); // Errore! Non posso fare una copia
398
+ // v.push_back(h ); // Errore! Non posso fare una copia
394
399
v.push_back (move (p)); // Ok! Trasferisco l'ownership
395
- // cout << *p << endl; // Errore a runtime!!!! p non è più mio!
400
+ // cout << *h << endl; // Errore a runtime!!!! h non è più mio!
396
401
397
402
unique_ptr<int > p3{allocaArray ()};
398
403
cout << *p3 << endl; // posso dereferenziare come un puntatore normale
0 commit comments