-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcarminati-esercizi-02.html
696 lines (691 loc) · 109 KB
/
carminati-esercizi-02.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="it-IT" xml:lang="it-IT">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc-markdown-css-theme" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<meta name="author" content="Leonardo Carminati" />
<meta name="author" content="Maurizio Tomasi" />
<title>Lezione 2: Analisi dei dati (classe Vettore)</title>
<link rel="stylesheet" href="css/theme.css" />
<link rel="stylesheet" href="css/skylighting-solarized-theme.css" />
</head>
<body>
<header>
<h1 class="title">Lezione 2: Analisi dei dati (classe Vettore)</h1>
<blockquote class="metadata">
<p class="author">
Leonardo CarminatiMaurizio Tomasi
</p>
<p class="date before-toc"><time datetime="A.A. 2024−2025">A.A. 2024−2025</time></p>
</blockquote>
</header>
<nav id="TOC" role="doc-toc">
<strong>Contents</strong><label for="contents">⊕</label>
<input type="checkbox" id="contents">
<ul>
<li><a href="#esercizio-2.0" id="toc-esercizio-2.0">Esercizio 2.0 - Creazione della classe Vettore</a>
<ul>
<li><a href="#header-file-della-classe" id="toc-header-file-della-classe">Header file della classe</a></li>
<li><a href="#esempio-di-implementazione-della-classe" id="toc-esempio-di-implementazione-della-classe">Esempio di implementazione della classe</a></li>
<li><a href="#programma-di-test" id="toc-programma-di-test">Programma di test</a></li>
</ul></li>
<li><a href="#esercizio-2.1" id="toc-esercizio-2.1">Esercizio 2.1 - Completamento della classe <code>Vettore</code></a>
<ul>
<li><a href="#copy-constructor" id="toc-copy-constructor">Copy constructor</a></li>
<li><a href="#operatore-di-assegnazione" id="toc-operatore-di-assegnazione">Operatore di assegnazione</a></li>
<li><a href="#il-puntatore-this" id="toc-il-puntatore-this">Il puntatore <code>this</code></a></li>
<li><a href="#operatore-di-accesso" id="toc-operatore-di-accesso">Operatore di accesso <code>[]</code></a></li>
<li><a href="#esempio-di-codice" id="toc-esempio-di-codice">Esempio di codice</a></li>
</ul></li>
<li><a href="#esercizio-2.2" id="toc-esercizio-2.2">Esercizio 2.2 - Codice di analisi dati utilizzando la classe <code>Vettore</code> (da consegnare)</a>
<ul>
<li><a href="#struttura-del-programma" id="toc-struttura-del-programma">Struttura del programma</a></li>
<li><a href="#implementazione-delle-funzioni" id="toc-implementazione-delle-funzioni">Implementazione delle funzioni</a></li>
<li><a href="#passaggio-dati-by-reference-con-qualificatore-const" id="toc-passaggio-dati-by-reference-con-qualificatore-const">Passaggio dati <em>by reference</em> con qualificatore <code>const</code></a></li>
<li><a href="#il-makefile" id="toc-il-makefile">Il Makefile</a></li>
<li><a href="#tipo-del-parametro-di-calcolamediana" id="toc-tipo-del-parametro-di-calcolamediana">Tipo del parametro di <code>CalcolaMediana</code></a></li>
<li><a href="#approfondimenti" id="toc-approfondimenti">Approfondimenti</a></li>
<li><a href="#eccezioni-in-c" id="toc-eccezioni-in-c">Eccezioni in C++</a></li>
</ul></li>
<li><a href="#errori-comuni" id="toc-errori-comuni">Errori comuni</a></li>
</ul>
</nav>
<main>
<p>[La pagina con la spiegazione originale degli esercizi si trova qui: <a href="https://labtnds.docs.cern.ch/Lezione2/Lezione2/" class="uri">https://labtnds.docs.cern.ch/Lezione2/Lezione2/</a>.]</p>
<p>In questa seconda lezione affronteremo gli stessi problemi della prima (lettura di dati da un file, calcolo di media, varianza e mediana) utilizzando però un contenitore di dati di nostra invenzione, idealmente più evoluto del semplice array dinamico del C. A questo proposito nella prima parte della lezione costruiremo la nostra prima classe, la classe <code>Vettore</code>, che sostituirà l’array dinamico del C. Nella seconda parte adatteremo le funzioni già scritte nella lezione scorsa in modo che possano funzionare con oggetti di tipo <code>Vettore</code>. Quindi in sintesi:</p>
<ul>
<li>Tipo di dato da leggere è constituito da numeri <code>double</code> immagazzinati in un file <a href="1941.txt">1941.txt</a>.</li>
<li>Tipo di contenitore di dati è la classe <code>Vettore</code> che scriveremo noi.</li>
<li>Operazioni sui dati vengono svolte mediante funzioni che lavorano su oggetti di tipo <code>Vettore</code>.</li>
</ul>
<h1 id="esercizio-2.0">Esercizio 2.0 - Creazione della classe Vettore</h1>
<p>In questo esercizio proviamo ad implementare una classe che abbia come data membri privati un intero (dimensione del vettore) ed un puntatore a <code>double</code> (puntatore alla zona di memoria dove sono immagazzinati i dati).</p>
<p>La classe dovrà poi implementare:</p>
<ul>
<li>Un costruttore di default, che assegni valori nulli alla lunghezza del vettore ed al puntatore.</li>
<li>Un costruttore che abbia come argomento un intero: questo deve creare un vettore di lunghezza uguale al valore dell’intero e tutte le componenti nulle (usando un <code>new</code> per allocare la memoria necessaria).</li>
<li>Un distruttore: deve chiaramente deallocare con <code>delete[]</code> la zona di memoria allocata con new.</li>
<li>Dei metodi per inserire e leggere i valori della componenti: questi metodi devono controllare che l’indice delle componenti richieste sia compatibile con la lunghezza del vettore.</li>
</ul>
<h2 id="header-file-della-classe">Header file della classe</h2>
<p>L’header file della classe iniziale (<code>vettore.h</code>) potrebbe essere così:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#pragma once</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="co">// La scrittura `#pragma once` è equivalente a scrivere:</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co">//</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="co">// #ifndef __vettore_h__</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="co">// #define __vettore_h__</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co">// #endif</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="co">//</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="co">// ma basta una riga anziché tre, ed evita di dover ricopiare</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="co">// `__vettore_h__` due volte (spesso fonte di errore tra gli</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="co">// studenti, che fanno copia-e-incolla da un file all'altro!)</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><iostream></span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vettore <span class="op">{</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> Vettore<span class="op">();</span> <span class="co">// costruttore di default</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> Vettore<span class="op">(</span><span class="dt">int</span> N<span class="op">);</span> <span class="co">// costruttore con dimensione del vettore</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="op">~</span>Vettore<span class="op">();</span> <span class="co">// distruttore</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> GetN<span class="op">()</span> <span class="at">const</span> <span class="op">{</span> <span class="co">// restituisce la dimensione del vettore</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">m_N</span><span class="op">;</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a> <span class="co">// Modifica la componente i-esima</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a> <span class="dt">void</span> SetComponent<span class="op">(</span><span class="dt">int</span><span class="op">,</span> <span class="dt">double</span><span class="op">);</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a> <span class="co">// Accede alla componente i-esima</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a> <span class="dt">double</span> GetComponent<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="at">const</span><span class="op">;</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a> <span class="dt">void</span> Scambia<span class="op">(</span><span class="dt">int</span><span class="op">,</span> <span class="dt">int</span><span class="op">);</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> <span class="va">m_N</span><span class="op">;</span> <span class="co">// dimensione del vettore</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a> <span class="dt">double</span> <span class="op">*</span> <span class="va">m_v</span><span class="op">;</span> <span class="co">// puntatore all'array dei dati</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a> <span class="dt">void</span> crashIfInvalidIndex<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="at">const</span><span class="op">;</span> <span class="co">// verifica che l'indice di un elemento sia corretto</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a><span class="co">// Necessario usare `;` dopo la parentesi graffa</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a><span class="co">// *solo* quando si chiude una classe!</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a></span></code></pre></div>
<ul>
<li><p>L’utilizzo del costrutto <code>#ifndef</code>…<code>#define</code>…<code>#endif</code> al posto di <code>#pragma once</code> merita una spiegazione. Queste direttive di preprocessore sono normalmente utilizzate per evitare inclusioni multiple di uno stesso header file che, nel caso specifico, porterebbero ad una doppia dichiarazione della classe <code>Vettore</code>. Immaginate infatti di voler compilare un codice <code>main.cpp</code> che includa sia <code>vettore.h</code> che <code>funzioni.h</code>, e che quest’ultimo file abbia bisogno di <code>vettore.h</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">////////////////////////////////////////</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="co">// File vettore.h, che implementa la classe `Vettore`</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vettore <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="co">////////////////////////////////////////</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="co">// File funzioni.h</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"vettore.h"</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> calcolaMedia<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&</span> v<span class="op">);</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="co">// ..</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="co">////////////////////////////////////////</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="co">// File main.cpp</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"vettore.h"</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"funzioni.h"</span></span></code></pre></div>
<p>In fase di compilazione il compilatore si lamenterebbe per una doppia dichiarazione della classe <code>Vettore</code>, perché il contenuto di <code>vettore.h</code> viene <strong>copiato due volte</strong> in <code>main.cpp</code>:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// File main.cpp come viene visto dal compilatore:</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="co">// La riga #include "vettore.h" viene sostituita col</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="co">// contenuto del file vettore.h:</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vettore <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="co">// Appena sotto, la riga #include "funzioni.h" viene</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="co">// sostituita col suo contenuto…</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="co">// …che però richiede nella prima riga di includere</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="co">// di nuovo vettore.h:</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vettore <span class="op">{</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> calcolaMedia<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&</span> v<span class="op">);</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a><span class="co">// Ora continua col contenuto di `main.cpp`</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
<p>Se si riporta lo stesso esempio sopra senza però i commenti, è chiaro dove sta il problema:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vettore <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vettore <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> calcolaMedia<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&</span> v<span class="op">);</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
<p>La classe <code>Vettore</code> è stata inclusa due volte! La soluzione migliore a questo problema <em>non</em> è quella di rimuovere uno dei due <code>#include</code>, perché sono entrambi logicamente necessari: il primo in <code>main.cpp</code> serve perché nel <code>main</code> verosimilmente si deve usare <code>Vettore</code>, il secondo in <code>funzioni.h</code> serve per dare un senso alla definizione di <code>calcolaMedia</code>.</p>
<p>Con il meccanismo basato su <code>#ifndef …</code>, alla prima inclusione di <code>vettore.h</code>, viene creata una “variabile” <code>__vettore_h__</code> (il termine esatto è <em>macro</em>). Al secondo tentativo di inclusione l’esistenza di <code>__vettore_h__</code> globale forza il compilatore a saltare tutte le righe tra <code>#define</code> ed <code>#endif</code>, di fatto evitando la seconda inclusione del file <code>vettore.h</code>.</p>
<p>La scrittura <code>#pragma once</code> abbrevia la sequenza di <code>#ifndef</code>/<code>#define</code>/<code>#endif</code> in una sola riga; non è nello standard C++, ma è così comoda che è implementata su tutti i compilatori C++ in commercio.</p>
<p>Questa parte è spiegata anche sulle <a href="tomasi-lezione-02.html#/uso-di-header-files">slides</a>.</p></li>
<li><p>Notate l’impementazione <em>in-line</em> del metodo <code>GetN()</code>: i metodi di una classe possono essere anche implementati direttamente nell’header file (<code>.h</code>) e non nel file <code>.cpp</code>. L’implementazione inline implica che il compilatore metta una copia della funzione ogni volta che questa viene chiamata, anziché mantenerne <strong>una sola copia</strong> ed invocarla da vari punti del codice. In questo modo il file eseguibile aumenta di dimensioni (ci sono ora N copie dell’implementazione di <code>GetN()</code>), ma le prestazioni sono migliori in quanto non si deve effettuare una chiamata alla funzione. In genere l’implementazione inline viene effettuata per funzioni brevi e invocate spesso.</p></li>
<li><p>Notate l’uso del qualificatore <code>const</code> nella definizione del metodo <code>GetN()</code>: in questo modo ogni istruzione dentro <code>GetN()</code> che tenti di modificare il contenuto della classe verrà segnalata come errore di compilazione. Il metodo <code>GetN()</code> è un metodo di accesso e logicamente non ci aspettiamo che effettui alcuna operazione di modifica del contenuto della classe: in questo caso è buona pratica dichiararlo <code>const</code> al fine di rendere l’utilizzo della nostra classe da parte di eventuali utenti più sicuro.</p></li>
</ul>
<h2 id="esempio-di-implementazione-della-classe">Esempio di implementazione della classe</h2>
<p>Il file di implementazione <code>vettore.cpp</code> potrebbe essere così:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"vettore.h"</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><iomanip></span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><cmath></span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><cstdlib></span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><cassert></span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="co">// Costruttore senza argomenti</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>Vettore<span class="op">::</span>Vettore<span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a> <span class="va">m_N</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span> <span class="op">=</span> <span class="kw">nullptr</span><span class="op">;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a><span class="co">// Costruttore con dimensione</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>Vettore<span class="op">::</span>Vettore<span class="op">(</span><span class="dt">int</span> N<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span>N <span class="op"><</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a> cerr <span class="op"><<</span> <span class="st">"Errore, la dimensione deve essere positiva anziché "</span> <span class="op"><<</span> N <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a> exit<span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a> <span class="va">m_N</span> <span class="op">=</span> N<span class="op">;</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span> <span class="op">=</span> <span class="kw">new</span> <span class="dt">double</span><span class="op">[</span>N<span class="op">];</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> N<span class="op">;</span> <span class="op">++</span>k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span><span class="op">[</span>k<span class="op">]</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>Vettore<span class="op">::~</span>Vettore<span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a> <span class="kw">delete</span><span class="op">[]</span> <span class="va">m_v</span><span class="op">;</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> Vettore<span class="op">::</span>crashIfInvalidIndex<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="at">const</span> <span class="op">{</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true" tabindex="-1"></a> <span class="co">// Se `i` non è un indice valido nell'array, stampa un messaggio</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true" tabindex="-1"></a> <span class="co">// di errore e termina il programma</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span>i <span class="op"><</span> <span class="dv">0</span> <span class="op">||</span> i <span class="op">>=</span> <span class="va">m_N</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true" tabindex="-1"></a> cerr <span class="op"><<</span> <span class="st">"Errore, indice "</span> <span class="op"><<</span> i <span class="op"><<</span> <span class="st">", dimensione "</span> <span class="op"><<</span> <span class="va">m_N</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true" tabindex="-1"></a> exit<span class="op">(</span><span class="dv">1</span><span class="op">);</span></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-41"><a href="#cb5-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-42"><a href="#cb5-42" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> Vettore<span class="op">::</span>SetComponent<span class="op">(</span><span class="dt">int</span> i<span class="op">,</span> <span class="dt">double</span> a<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-43"><a href="#cb5-43" aria-hidden="true" tabindex="-1"></a> crashIfInvalidIndex<span class="op">(</span>i<span class="op">);</span></span>
<span id="cb5-44"><a href="#cb5-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-45"><a href="#cb5-45" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span><span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> a<span class="op">;</span></span>
<span id="cb5-46"><a href="#cb5-46" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-47"><a href="#cb5-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-48"><a href="#cb5-48" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> Vettore<span class="op">::</span>GetComponent<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="at">const</span> <span class="op">{</span></span>
<span id="cb5-49"><a href="#cb5-49" aria-hidden="true" tabindex="-1"></a> crashIfInvalidIndex<span class="op">(</span>i<span class="op">);</span></span>
<span id="cb5-50"><a href="#cb5-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-51"><a href="#cb5-51" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">m_v</span><span class="op">[</span>i<span class="op">];</span></span>
<span id="cb5-52"><a href="#cb5-52" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-53"><a href="#cb5-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-54"><a href="#cb5-54" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> Vettore<span class="op">::</span>Scambia<span class="op">(</span><span class="dt">int</span> primo<span class="op">,</span> <span class="dt">int</span> secondo<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-55"><a href="#cb5-55" aria-hidden="true" tabindex="-1"></a> <span class="co">// Verifica che entrambi gli indici siano corretti</span></span>
<span id="cb5-56"><a href="#cb5-56" aria-hidden="true" tabindex="-1"></a> crashIfInvalidIndex<span class="op">(</span>primo<span class="op">);</span></span>
<span id="cb5-57"><a href="#cb5-57" aria-hidden="true" tabindex="-1"></a> crashIfInvalidIndex<span class="op">(</span>secondo<span class="op">);</span></span>
<span id="cb5-58"><a href="#cb5-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-59"><a href="#cb5-59" aria-hidden="true" tabindex="-1"></a> <span class="dt">double</span> temp <span class="op">=</span> <span class="va">m_v</span><span class="op">[</span>primo<span class="op">];</span></span>
<span id="cb5-60"><a href="#cb5-60" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span><span class="op">[</span>primo<span class="op">]</span> <span class="op">=</span> <span class="va">m_v</span><span class="op">[</span>secondo<span class="op">];</span></span>
<span id="cb5-61"><a href="#cb5-61" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span><span class="op">[</span>secondo<span class="op">]</span> <span class="op">=</span> temp<span class="op">;</span></span>
<span id="cb5-62"><a href="#cb5-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-63"><a href="#cb5-63" aria-hidden="true" tabindex="-1"></a> <span class="co">// Equivalente a:</span></span>
<span id="cb5-64"><a href="#cb5-64" aria-hidden="true" tabindex="-1"></a> <span class="co">//</span></span>
<span id="cb5-65"><a href="#cb5-65" aria-hidden="true" tabindex="-1"></a> <span class="co">// double temp = GetComponent(primo);</span></span>
<span id="cb5-66"><a href="#cb5-66" aria-hidden="true" tabindex="-1"></a> <span class="co">// SetComponent(primo, GetComponent(secondo));</span></span>
<span id="cb5-67"><a href="#cb5-67" aria-hidden="true" tabindex="-1"></a> <span class="co">// SetComponent(secondo, temp);</span></span>
<span id="cb5-68"><a href="#cb5-68" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-69"><a href="#cb5-69" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-70"><a href="#cb5-70" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> <span class="op">&</span> Vettore<span class="op">::</span><span class="kw">operator</span><span class="op">[](</span><span class="dt">int</span> i<span class="op">)</span> <span class="at">const</span> <span class="op">{</span></span>
<span id="cb5-71"><a href="#cb5-71" aria-hidden="true" tabindex="-1"></a> crashIfInvalidIndex<span class="op">(</span>i<span class="op">);</span></span>
<span id="cb5-72"><a href="#cb5-72" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">m_v</span><span class="op">[</span>i<span class="op">];</span></span>
<span id="cb5-73"><a href="#cb5-73" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Notate l’ultimo metodo implementato (dovete ovviamente aggiungerlo anche nell’header file della classe) che rappresenta l’overloading dell’operatore di accesso <code>[]</code> ad un elemento (eg. <code>double a = v[2]</code> se <code>v</code> è un oggetto di tipo <code>Vettore</code>). Questo è spiegato anche sulle <a href="tomasi-lezione-02.html#operator-array">slide addizionali</a>.</p>
<h2 id="programma-di-test">Programma di test</h2>
<p>Questo programma usa un copy constructor per creare il <code>Vettore c</code> ed un’assegnazione per il <code>Vettore b</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"vettore.h"</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><iostream></span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a> <span class="co">// costruttore senza argomenti → crea un vettore di dimensione nulla</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a> Vettore vnull<span class="op">;</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore vnull: dimensione = "</span> <span class="op"><<</span> vnull<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> vnull<span class="op">.</span>getN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> vnull<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a> <span class="co">// costruttore con intero: costruisco un vettore di lunghezza 10</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a> Vettore v<span class="op">(</span><span class="dv">10</span><span class="op">);</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore v: dimensione = "</span> <span class="op"><<</span> v<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> v<span class="op">.</span>GetN<span class="op">();</span> <span class="op">++</span>k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> v<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> comp <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Componente "</span> <span class="op"><<</span> comp <span class="op"><<</span> <span class="st">" = "</span> <span class="op"><<</span> v<span class="op">.</span>GetComponent<span class="op">(</span>comp<span class="op">)</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a> <span class="co">// Cambio la componente alla posizione `comp`</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a> v<span class="op">.</span>SetComponent<span class="op">(</span>comp<span class="op">,</span> <span class="op">-</span><span class="dv">999</span><span class="op">);</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> v<span class="op">.</span>GetN<span class="op">();</span> <span class="op">++</span>k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> v<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true" tabindex="-1"></a> <span class="co">// Anche come puntatore a memoria dinamica</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true" tabindex="-1"></a> Vettore <span class="op">*</span> vp <span class="op">=</span> <span class="kw">new</span> Vettore<span class="op">(</span><span class="dv">10</span><span class="op">);</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore vp: dimensione = "</span> <span class="op"><<</span> vp<span class="op">-></span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> v<span class="op">.</span>GetN<span class="op">();</span> <span class="op">++</span>k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> vp<span class="op">-></span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true" tabindex="-1"></a> <span class="kw">delete</span> vp<span class="op">;</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 id="esercizio-2.1">Esercizio 2.1 - Completamento della classe <code>Vettore</code></h1>
<p>La classe <code>vettore</code> costruita sopra non è però ancora completa, anzi può essere addirittura pericolosa! In particolare vogliamo:</p>
<ol type="1">
<li><p>Aggiungere la possibilità di costruire un <code>Vettore</code> a partire da un <code>Vettore</code> esistente (<em>costruttore di copia</em>)</p></li>
<li><p>Aggiungere la possibilità di eguagliare due oggetti di tipo <code>vettore</code> (<em>operatore di assegnazione</em>)</p></li>
<li><p>Aggiungere un operatore di accesso rapido alle componenti (<code>[]</code>).</p></li>
</ol>
<h2 id="copy-constructor">Copy constructor</h2>
<p>Il <em>copy constructor</em> (o costruttore di copia) viene utilizzato per creare una copia di un <code>Vettore</code> esistente: esso deve accettare in input un <code>Vettore</code> e costruirne una copia del <code>Vettore</code> argomento.</p>
<p>Il <em>copy constructor</em> viene invocato implicitamente ogni volta che utilizziamo sintassi come:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>Vettore a<span class="op">;</span> <span class="co">// costruttore standard senza argomenti</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>Vettore b <span class="op">=</span> a<span class="op">;</span> <span class="co">// copy constructor</span></span></code></pre></div>
<p>oppure la sintassi equivalente:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>Vettore a<span class="op">;</span> <span class="co">// costruttore standard senza argomenti</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>Vettore b<span class="op">(</span>a<span class="op">);</span> <span class="co">// copy constructor (idem al caso sopra)</span></span></code></pre></div>
<p>ed in tutti i casi in cui si passa un oggetto per valore. Il compilatore mette a disposizione un costruttore di copia di default che eguaglia i data membri. In questo caso i due puntatori <code>m_v</code> dei due oggetti <code>Vettore</code> punterebbero alla stessa area di memoria generando possibili problemi di memoria. In questi casi si deve procedere a fornire al compilatore una implementazione esplicita del costruttore di copia, che si effettua seguendo questi passaggi:</p>
<ul>
<li><p>Il <em>copy constructor</em> viene dichiarato nell’header con questo prototipo:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>Vettore<span class="op">(</span><span class="at">const</span> Vettore<span class="op">&);</span></span></code></pre></div></li>
<li><p>Nell’implementazione, dobbiamo assicurarci che l’oggetto costruito abbia la sua zona di memoria riservata:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">// overloading costruttore di copia</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>Vettore<span class="op">::</span>Vettore<span class="op">(</span><span class="at">const</span> Vettore<span class="op">&</span> V<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> <span class="va">m_N</span> <span class="op">=</span> V<span class="op">.</span>GetN<span class="op">();</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a> <span class="co">// Il vettore `V` ha già la sua memoria allocata, ma qui dobbiamo</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a> <span class="co">// richiedere nuova memoria per l'oggetto corrente</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span> <span class="op">=</span> <span class="kw">new</span> <span class="dt">double</span><span class="op">[</span><span class="va">m_N</span><span class="op">];</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> <span class="va">m_N</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span><span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> V<span class="op">.</span>GetComponent<span class="op">(</span>i<span class="op">);</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div></li>
</ul>
<h2 id="operatore-di-assegnazione">Operatore di assegnazione</h2>
<p>L’ <em>operatore di assegnazione</em> viene utilizzato per eguagliare un vettore ad un altro (entrambi già esistenti); esso viene invocato implicitamente ogni volta che utilizziamo una sintassi come la seguente:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>Vettore a <span class="op">;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="co">// ... riempimento delle componenti di a</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>Vettore b <span class="op">;</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="co">// ... riempimento delle componenti di b</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Qui invoco l'operatore di assegnazione</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>a <span class="op">=</span> b<span class="op">;</span></span></code></pre></div>
<p>oppure la sintassi equivalente, ma più ostica:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>Vettore a<span class="op">;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="co">// ... riempimento delle componenti di a</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>Vettore b<span class="op">;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="co">// ... riempimento delle componenti di b</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>a<span class="op">.</span><span class="kw">operator</span><span class="op">=(</span>b<span class="op">);</span></span></code></pre></div>
<p>In questo caso <code>a</code> e <code>b</code> sono oggetti della stessa classe. Di fatto, un’assegnazione come <code>a = b</code> non è altro che una abbreviazione per indicare la chiamata ad un metodo della classe di nome <code>operator=</code>:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>a<span class="op">.</span><span class="kw">operator</span><span class="op">=(</span>b<span class="op">);</span></span></code></pre></div>
<p>Il compilatore fornisce un’implementazione di default di questo operatore, che corrisponde ad un assegnazione membro a membro di tutti i data membri. Nel caso di <code>Vettore</code>, il compilatore C++ genera quindi un costruttore di copia come il seguente:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Il C++ genera automaticamente questo operatore di assegnazione</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="co">// (che però in questo caso particolare è sbagliato!)</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>Vettore <span class="op">&</span> Vettore<span class="op">::</span><span class="kw">operator</span><span class="op">=(</span><span class="at">const</span> Vettore <span class="op">&</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="va">m_N</span> <span class="op">=</span> v<span class="op">.</span><span class="va">m_N</span><span class="op">;</span> <span class="co">// Questo andrebbe pure bene…</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span> <span class="op">=</span> v<span class="op">.</span><span class="va">m_v</span><span class="op">;</span> <span class="co">// …ma questo è sbagliato!</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a> <span class="co">// Se aggiungessimo altri membri alla Classe vettore, il C++</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a> <span class="co">// metterebbe automaticamente qui anche l'assegnazione di questi</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a> <span class="co">// nuovi membri</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In casi come quello di <code>Vettore</code> però, questo operatore di assegnazione non è corretto: il puntatore <code>m_v</code> è ora condiviso tra l’oggetto <code>V</code> e il nuovo oggetto. Ecco un codice che mostra dove sta il problema:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>Vettore a <span class="op">;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="co">// ... riempimento delle componenti di a</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>Vettore b <span class="op">;</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="co">// ... riempimento delle componenti di b</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Qui invoco l'operatore di assegnazione, ma siccome</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a><span class="co">// sto usando quello di default del C++, il valore di</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="co">// a.m_v diventerà uguale a quello di b.m_v</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>a <span class="op">=</span> b<span class="op">;</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a><span class="co">// A causa dell'errore sopra, SetElement modifica sia</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a><span class="co">// l'elemento n. 10 in `b` che quello in `a`: infatti</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="co">// a.m_v e b.m_v puntano alla stessa area di memoria!</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>b<span class="op">.</span>SetElement<span class="op">(</span><span class="dv">0</span><span class="op">,</span> <span class="dv">10</span><span class="op">);</span></span></code></pre></div>
<p>Dobbiamo quindi realizzare un’implementazione sicura dell’assegnazione, facendo una copia dei dati in una nuova locazione di memoria anziché copiare superficialmente il valore di <code>m_v</code>.</p>
<p>Nel nostro caso, l’header file <code>vettore.h</code> dovrà quindi contenere una dichiarazione:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>Vettore<span class="op">&</span> <span class="kw">operator</span><span class="op">=(</span><span class="at">const</span> Vettore<span class="op">&);</span></span></code></pre></div>
<p>Una possibile implementazione è data qui sotto:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a> <span class="co">// overloading operatore di assegnazione</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a> Vettore<span class="op">&</span> Vettore<span class="op">::</span><span class="kw">operator</span><span class="op">=(</span><span class="at">const</span> Vettore<span class="op">&</span> V<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a> <span class="va">m_N</span> <span class="op">=</span> V<span class="op">.</span>GetN<span class="op">();</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span><span class="va">m_v</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">delete</span><span class="op">[]</span> <span class="va">m_v</span><span class="op">;</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a> <span class="co">// Qui richiediamo una nuova area di memoria</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span> <span class="op">=</span> <span class="kw">new</span> <span class="dt">double</span><span class="op">[</span><span class="va">m_N</span><span class="op">];</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a> <span class="co">// Copiamo nella nuova area di memoria gli elementi di `V`</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op"><</span> <span class="va">m_N</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span><span class="op">[</span>i<span class="op">]</span> <span class="op">=</span> V<span class="op">.</span>GetComponent<span class="op">(</span>i<span class="op">);</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span><span class="op">;</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span></code></pre></div>
<h2 id="il-puntatore-this">Il puntatore <code>this</code></h2>
<p>Il puntatore <code>this</code> indica un puntatore all’oggetto cui si sta applicando un metodo. È particolarmente utile in alcune occasioni, come nel caso dell’operatore di assegnazione, in cui si deve restituire una copia dell’oggetto corrente.</p>
<p>(Se conoscete Python, il valore <code>*this</code> dei metodi C++ è equivalente al <code>self</code> dei metodi Python: ma in Python è esplicito, mentre in C++ la sua presenza è implicita.)</p>
<h2 id="operatore-di-accesso">Operatore di accesso <code>[]</code></h2>
<p>Se vogliamo semplificare la codifica dell’accesso alle componenti di un <code>Vettore</code> (sia in lettura sia in scrittura ) potremmo pensare di fare un <em>overloading</em> dell’operatore di accesso <code>operator[](int)</code>. Questo permetterebbe ad esempio di accedere alla seconda componente di un vettore v semplicemente scrivendo</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> a <span class="op">=</span> v<span class="op">[</span><span class="dv">1</span><span class="op">]</span></span></code></pre></div>
<p>Per aggiungere questa funzionalità alla nostra classe <code>Vettore</code> dobbiamo come al solito compiere queste azioni:</p>
<ul>
<li><p>Aggiungere la dichiarazione del metodo nell’header file (<code>.h</code>):</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span><span class="op">&</span> <span class="kw">operator</span><span class="op">[](</span><span class="dt">int</span><span class="op">)</span> <span class="at">const</span><span class="op">;</span></span></code></pre></div></li>
<li><p>Aggiungere l’implementazione del metodo nel file di implementazione (<code>.cpp</code>):</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span><span class="op">&</span> Vettore<span class="op">::</span><span class="kw">operator</span><span class="op">[]</span> <span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="at">const</span> <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a> crashIfInvalidIndex<span class="op">(</span>i<span class="op">);</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">m_v</span><span class="op">[</span>i<span class="op">];</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div></li>
</ul>
<h2 id="esempio-di-codice">Esempio di codice</h2>
<p>A questo punto possiamo utilizzare il seguente codice di test che include anche un esempio di utilizzo di <em>copy constructor</em> , <em>operatore di assegnazione</em> e <em>operatore di accesso</em>.</p>
<p><strong>Avvertenza</strong>: Questo esempio di codice darebbe problemi di <em>memory corruption</em> senza l’implementazione corretta del copy constructor e dell’operatore di assegnazione ma basandosi su quelli generati automaticamente dal compilatore! Infatti avremmo ottenuto due vettori che condividono esattamente la stessa area di memoria: una modifica su un vettore implica che anche l’altro venga modificato. Avendo implementato esplicitamente ed in maniera corretta i due operatori questo problema non si presenta.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"Vettore.h"</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><iostream></span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">;</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a> <span class="co">// costruttore senza argomenti → crea un vettore di dimensione nulla</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a> Vettore vnull<span class="op">;</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore vnull: dimensione = "</span> <span class="op"><<</span> vnull<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> vnull<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> vnull<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a> <span class="co">// construttore con intero: costruisco un OGGETTO di tipo vettore di</span></span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a> <span class="co">// lunghezza 10</span></span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a> Vettore v<span class="op">(</span><span class="dv">10</span><span class="op">);</span></span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore v: = dimensione = "</span> <span class="op"><<</span> v<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> v<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> v<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-21"><a href="#cb21-21" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb21-22"><a href="#cb21-22" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-23"><a href="#cb21-23" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> comp <span class="op">=</span> <span class="dv">3</span><span class="op">;</span></span>
<span id="cb21-24"><a href="#cb21-24" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Componente "</span> <span class="op"><<</span> comp <span class="op"><<</span> <span class="st">" = "</span> <span class="op"><<</span> v<span class="op">.</span>GetComponent<span class="op">(</span>comp<span class="op">)</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-25"><a href="#cb21-25" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Componente "</span> <span class="op"><<</span> comp <span class="op"><<</span> <span class="st">" = "</span> <span class="op"><<</span> v<span class="op">[</span>comp<span class="op">]</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-26"><a href="#cb21-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-27"><a href="#cb21-27" aria-hidden="true" tabindex="-1"></a> v<span class="op">.</span>SetComponent<span class="op">(</span>comp<span class="op">,</span> <span class="op">-</span><span class="dv">999</span><span class="op">);</span></span>
<span id="cb21-28"><a href="#cb21-28" aria-hidden="true" tabindex="-1"></a> v<span class="op">[</span>comp<span class="op">]</span> <span class="op">=</span> <span class="op">-</span><span class="dv">999</span><span class="op">;</span></span>
<span id="cb21-29"><a href="#cb21-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-30"><a href="#cb21-30" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> v<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb21-31"><a href="#cb21-31" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> v<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-32"><a href="#cb21-32" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb21-33"><a href="#cb21-33" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-34"><a href="#cb21-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-35"><a href="#cb21-35" aria-hidden="true" tabindex="-1"></a> <span class="co">// anche come puntatore</span></span>
<span id="cb21-36"><a href="#cb21-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-37"><a href="#cb21-37" aria-hidden="true" tabindex="-1"></a> Vettore <span class="op">*</span>vp <span class="op">=</span> <span class="kw">new</span> Vettore<span class="op">(</span><span class="dv">10</span><span class="op">);</span></span>
<span id="cb21-38"><a href="#cb21-38" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore vp: = dimensione = "</span> <span class="op"><<</span> vp<span class="op">-></span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-39"><a href="#cb21-39" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> vp<span class="op">-></span>GetN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb21-40"><a href="#cb21-40" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> vp<span class="op">-></span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-41"><a href="#cb21-41" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb21-42"><a href="#cb21-42" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-43"><a href="#cb21-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-44"><a href="#cb21-44" aria-hidden="true" tabindex="-1"></a> <span class="co">// copy constructor: w viene creato come copia di v</span></span>
<span id="cb21-45"><a href="#cb21-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-46"><a href="#cb21-46" aria-hidden="true" tabindex="-1"></a> Vettore w <span class="op">=</span> v<span class="op">;</span> <span class="co">// oppure la sintassi equivalente: Vettore w(v);</span></span>
<span id="cb21-47"><a href="#cb21-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-48"><a href="#cb21-48" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore w: dimensione = "</span> <span class="op"><<</span> w<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-49"><a href="#cb21-49" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> w<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span></span>
<span id="cb21-50"><a href="#cb21-50" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> w<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-51"><a href="#cb21-51" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-52"><a href="#cb21-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-53"><a href="#cb21-53" aria-hidden="true" tabindex="-1"></a> v<span class="op">.</span>SetComponent<span class="op">(</span><span class="dv">4</span><span class="op">,</span> <span class="dv">99</span><span class="op">);</span> <span class="co">// </span><span class="al">WARNING</span><span class="co">: senza copy constructor opportuno, un</span></span>
<span id="cb21-54"><a href="#cb21-54" aria-hidden="true" tabindex="-1"></a> <span class="co">// cambio di v cambia anche w !!!!!!</span></span>
<span id="cb21-55"><a href="#cb21-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-56"><a href="#cb21-56" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore v: dimensione = "</span> <span class="op"><<</span> v<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-57"><a href="#cb21-57" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> v<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb21-58"><a href="#cb21-58" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> v<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-59"><a href="#cb21-59" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb21-60"><a href="#cb21-60" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-61"><a href="#cb21-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-62"><a href="#cb21-62" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore w: dimensione = "</span> <span class="op"><<</span> w<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-63"><a href="#cb21-63" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> w<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb21-64"><a href="#cb21-64" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> w<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-65"><a href="#cb21-65" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb21-66"><a href="#cb21-66" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-67"><a href="#cb21-67" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-68"><a href="#cb21-68" aria-hidden="true" tabindex="-1"></a> <span class="co">// operatore di assegnazione: prima creo Z e poi lo eguagli a w</span></span>
<span id="cb21-69"><a href="#cb21-69" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-70"><a href="#cb21-70" aria-hidden="true" tabindex="-1"></a> Vettore z<span class="op">;</span></span>
<span id="cb21-71"><a href="#cb21-71" aria-hidden="true" tabindex="-1"></a> z <span class="op">=</span> w<span class="op">;</span></span>
<span id="cb21-72"><a href="#cb21-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-73"><a href="#cb21-73" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Vettore z: dimensione = "</span> <span class="op"><<</span> z<span class="op">.</span>GetN<span class="op">()</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-74"><a href="#cb21-74" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> z<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb21-75"><a href="#cb21-75" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> z<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">)</span> <span class="op"><<</span> <span class="st">" "</span><span class="op">;</span></span>
<span id="cb21-76"><a href="#cb21-76" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb21-77"><a href="#cb21-77" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb21-78"><a href="#cb21-78" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-79"><a href="#cb21-79" aria-hidden="true" tabindex="-1"></a> <span class="kw">delete</span> vp<span class="op">;</span></span>
<span id="cb21-80"><a href="#cb21-80" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-81"><a href="#cb21-81" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb21-82"><a href="#cb21-82" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 id="esercizio-2.2">Esercizio 2.2 - Codice di analisi dati utilizzando la classe <code>Vettore</code> (da consegnare)</h1>
<p>Proviamo ora a riscrivere il codice della prima lezione utilizzando un contenitore di dati più raffinato: la classe <code>Vettore</code> ci permetterà di riempire il contenitore dati controllando per esempio che non stiamo sforando la dimensione allocata. La classe <code>Vettore</code> inoltre mantiene al suo interno anche la sua dimensione (nel campo <code>m_N</code>): se dobbiamo calcolare la media degli elementi di un <code>Vettore</code> <strong>non dobbiamo più passare la dimensione come argomento esterno</strong>! Per svolgere questo esercizio dobbiamo:</p>
<ul>
<li>modificare tutte le funzioni in <code>funzioni.h</code> e <code>funzioni.cpp</code> in modo che lavorino con oggetti di tipo <code>Vettore</code> invece che con semplici array del C.</li>
<li>modificare il <code>main</code> in modo che utilizzi la nuova classe <code>Vettore</code> e le nuove funzioni.</li>
<li>modificare il <code>Makefile</code></li>
</ul>
<p>Se non ci riuscite da soli potete dare un’occhiata ai suggerimenti qui sotto.</p>
<h2 id="struttura-del-programma">Struttura del programma</h2>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><cstdlib></span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><string></span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><iostream></span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="co">// includo la dichiarazione della classe Vettore</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"Vettore.h"</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="co">// include la dichiarazione delle funzioni</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"funzioni.h"</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">;</span></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>argv<span class="op">[])</span> <span class="op">{</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a> <span class="co">// Vedi le slide</span></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a> test_statistical_functions<span class="op">();</span></span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span>argc <span class="op">!=</span> <span class="dv">3</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Uso del programma: "</span> <span class="op"><<</span> argv<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op"><<</span> <span class="st">" <n_data> <filename> "</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> ndata <span class="op">=</span> stoi<span class="op">(</span>argv<span class="op">[</span><span class="dv">1</span><span class="op">]);</span></span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a> <span class="dt">char</span> <span class="op">*</span>filename <span class="op">=</span> argv<span class="op">[</span><span class="dv">2</span><span class="op">];</span></span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a> Vettore v <span class="op">=</span> Read<span class="op">(</span>ndata<span class="op">,</span> filename<span class="op">);</span></span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a> Print<span class="op">(</span>v<span class="op">);</span></span>
<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"media = "</span> <span class="op"><<</span> CalcolaMedia<span class="op">(</span>v<span class="op">)</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"varianza = "</span> <span class="op"><<</span> CalcolaVarianza<span class="op">(</span>v<span class="op">)</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"mediana = "</span> <span class="op"><<</span> CalcolaMediana<span class="op">(</span>v<span class="op">)</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb22-34"><a href="#cb22-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-35"><a href="#cb22-35" aria-hidden="true" tabindex="-1"></a> Print<span class="op">(</span>v<span class="op">);</span></span>
<span id="cb22-36"><a href="#cb22-36" aria-hidden="true" tabindex="-1"></a> Print<span class="op">(</span>v<span class="op">,</span> <span class="st">"data_out.txt"</span><span class="op">);</span></span>
<span id="cb22-37"><a href="#cb22-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-38"><a href="#cb22-38" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb22-39"><a href="#cb22-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>La funzione <code>test_statistical_functions()</code> è spiegata nelle <a href="tomasi-lezione-02.html#/scrittura-di-test">slide di Tomasi</a>.</p>
<h2 id="implementazione-delle-funzioni">Implementazione delle funzioni</h2>
<ul>
<li><p>L’header file (<code>.h</code>) potrebbe risultare così:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#pragma once</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><fstream></span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im"><iostream></span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"Vettore.h"</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>Vettore Read<span class="op">(</span><span class="dt">int</span><span class="op">,</span> <span class="at">const</span> <span class="dt">char</span> <span class="op">*);</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> CalcolaMedia<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&);</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> CalcolaVarianza<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&);</span></span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> CalcolaMediana<span class="op">(</span>Vettore<span class="op">);</span></span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> Print<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&);</span></span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> Print<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&,</span> <span class="at">const</span> <span class="dt">char</span> <span class="op">*);</span></span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> selection_sort<span class="op">(</span>Vettore <span class="op">&);</span></span></code></pre></div></li>
<li><p>Il file di implementazione (<code>.cpp</code>) potrebbe risultare così per il calcolo della media (aggiungere tutte le funzioni restanti):</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"funzioni.h"</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> CalcolaMedia<span class="op">(</span><span class="at">const</span> Vettore <span class="op">&</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">double</span> accumulo <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> k <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> k <span class="op"><</span> v<span class="op">.</span>GetN<span class="op">();</span> k<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a> accumulo <span class="op">+=</span> v<span class="op">.</span>GetComponent<span class="op">(</span>k<span class="op">);</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> accumulo <span class="op">/</span> <span class="dt">double</span> <span class="op">(</span>v<span class="op">.</span>GetN<span class="op">())</span> <span class="op">;</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div></li>
<li><p>Assicuratevi di implementare i test con <code>assert</code> come spiegato in <a href="tomasi-lezione-02.html#/esercizio-1.1-assert">questa slide</a>: il codice fornito nella slide va bene per gli esercizi della scorsa lezione, che richiedono di passare sia l’array che la lunghezza dell’array, ma è facile adattarli al caso di oggi. (Se non ci riuscite, chiedete al docente!)</p></li>
</ul>
<h2 id="passaggio-dati-by-reference-con-qualificatore-const">Passaggio dati <em>by reference</em> con qualificatore <code>const</code></h2>
<p>Nella funzione <code>CalcolaMedia</code>, il vettore di input viene passato con la sintassi <code>const Vettore & v</code>, quindi il passaggio avviene <em>by reference</em> evitando una inutile e pesante copia dell’oggetto vettore di input. Il passaggio <em>by reference</em> darebbe alla funzione la possibilità di modificare (per sbaglio) il contenuto del vettore del <code>main</code>: per questo motivo si aggiunge il qualificatore <code>const</code>, che non permette (pena un errore di compilazione) operazioni di modifica del contenuto del vettore da dentro la funzione.</p>
<h2 id="il-makefile">Il Makefile</h2>
<p>Il makefile va modificato aggiungendo la compilazione della classe <code>Vettore</code>:</p>
<pre><code>esercizio2.2: esercizio2.2.o Vettore.o funzioni.o
g++ -o esercizio2.2 esercizio2.2.o Vettore.o funzioni.o
funzioni.o: funzioni.cpp funzioni.h Vettore.h
g++ -c -o funzioni.o funzioni.cpp
esercizio2.2.o: esercizio2.2.cpp funzioni.h Vettore.h
g++ -c -o esercizio2.2.o esercizio2.2.cpp
Vettore.o: Vettore.cpp Vettore.h
g++ -c -o Vettore.o Vettore.cpp
clean:
rm *.o
cleanall: clean
rm esercizio2.2</code></pre>
<h2 id="tipo-del-parametro-di-calcolamediana">Tipo del parametro di <code>CalcolaMediana</code></h2>
<p>Perché <code>CalcolaMedia</code> richiede un parametro di tipo <code>const Vettore &</code>, mentre <code>CalcolaMediana</code> richiede semplicemente il tipo <code>Vettore</code>?:</p>
<ul>
<li><p>Nel caso di <code>CalcolaMedia(...)</code> o <code>CalcolaVarianza(...)</code> il passaggio avviene <em>by reference</em> per ottimizzare l’uso della memoria. Con questa modalità di passaggio dati la funzione lavora sul <code>Vettore</code> del <code>main</code> e pertanto una modifica accidentale del <code>Vettore</code> di input all’interno della funzione ha un effetto anche nel <code>main</code>. Il qualificatore <code>const</code> vieta alla funzione di fare qualsiasi operazione di cambiamento del contenuto del vettore di input pena un errore di compilazione.</p></li>
<li><p>Nel caso invece di <code>CalcolaMediana(...)</code> il passaggio e’ effettuato <em>by value</em> e senza il qualificatore <code>const</code>: in questo modo permettiamo che il metodo proceda al riodinamento del <code>Vettore</code>. Dal momento che con il passaggio by value il <code>Vettore</code> nella funzione è una copia del <code>Vettore</code> di input ogni cambiamento effettuato nella funzione non si ripercuote sul <code>main</code>.</p></li>
</ul>
<h2 id="approfondimenti">Approfondimenti</h2>
<h3 id="semantica-di-move">Semantica di <code>move</code></h3>
<p>[Vedi anche le <a href="tomasi-lezione-02.html#/move-semantics">slide di Tomasi</a>]</p>
<p>La <em>move semantic</em> è un nuovo modo (dal C++11) di spostare le risorse in un modo ottimale evitando di creare copie non necessarie di oggetti temporanei ed è basato sulle <em>r-value</em> references. La potenza della <em>move semantic</em> si può capire affrontando il caso in cui si voglia costruire un oggetto della classe <code>Vettore</code> a partire dall’output di una funzione:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>Vettore v <span class="op">=</span> Read<span class="op">(</span>ndata<span class="op">,</span> filename<span class="op">);</span></span></code></pre></div>
<p>La funzione <code>Read()</code> restituirà un oggetto temporaneo di tipo `<code>Vettore</code> che poi verrà utilizzato come input del costruttore di copia per la creazione di <code>v</code>. Chiaramente questo riduce notevolmente le performance del nostro codice. Perché non realizzare un costruttore di copia (e un operatore di assegnazione) che siano in grado di rubare i data membri all’oggetto temporaneo senza dover copiare dati? Questo è lo spirito del <em>move constructor</em> e del <em>move assignment operator</em>:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="co">// overloading del move constructor</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>Vettore<span class="op">::</span>Vettore<span class="op">(</span>Vettore <span class="op">&&</span>V<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Calling move constructor"</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a> <span class="va">m_N</span> <span class="op">=</span> V<span class="op">.</span><span class="va">m_N</span><span class="op">;</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span> <span class="op">=</span> V<span class="op">.</span><span class="va">m_v</span><span class="op">;</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a> V<span class="op">.</span><span class="va">m_N</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a> V<span class="op">.</span><span class="va">m_v</span> <span class="op">=</span> <span class="kw">nullptr</span><span class="op">;</span></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Move constructor called"</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a><span class="co">// overloading del move assignment operator</span></span>
<span id="cb27-13"><a href="#cb27-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-14"><a href="#cb27-14" aria-hidden="true" tabindex="-1"></a>Vettore <span class="op">&</span>Vettore<span class="op">::</span><span class="kw">operator</span><span class="op">=(</span>Vettore <span class="op">&&</span>V<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-15"><a href="#cb27-15" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Calling move assignment operator "</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb27-16"><a href="#cb27-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">delete</span><span class="op">[]</span> <span class="va">m_v</span><span class="op">;</span></span>
<span id="cb27-17"><a href="#cb27-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-18"><a href="#cb27-18" aria-hidden="true" tabindex="-1"></a> <span class="va">m_N</span> <span class="op">=</span> V<span class="op">.</span><span class="va">m_N</span><span class="op">;</span></span>
<span id="cb27-19"><a href="#cb27-19" aria-hidden="true" tabindex="-1"></a> <span class="va">m_v</span> <span class="op">=</span> V<span class="op">.</span><span class="va">m_v</span><span class="op">;</span></span>
<span id="cb27-20"><a href="#cb27-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-21"><a href="#cb27-21" aria-hidden="true" tabindex="-1"></a> V<span class="op">.</span><span class="va">m_N</span> <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb27-22"><a href="#cb27-22" aria-hidden="true" tabindex="-1"></a> V<span class="op">.</span><span class="va">m_v</span> <span class="op">=</span> <span class="kw">nullptr</span><span class="op">;</span></span>
<span id="cb27-23"><a href="#cb27-23" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Move assignment operator called"</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb27-24"><a href="#cb27-24" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span><span class="op">;</span></span>
<span id="cb27-25"><a href="#cb27-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li>Notare la presenza della doppia <code>&&</code> nel tipo del parametro <code>V</code> di input: si sta dicendo al C++ che è richiesto un <em>r-value</em></li>
<li>Il <em>move constructor</em> e il <em>move assignment operator</em> semplicemente “rubano” i dati all’oggetto temporaneo (non c’è copia elemento per elemento)</li>
<li>Il puntatore dell’oggetto di input viene sganciato dai dati</li>
<li>Per vedere il <em>move constructor</em> all’opera potrebbe essere necessario aggiungere la flag <code>-fno-elide-constructors</code>, in modo da disattivare eventuali ottimizzazioni interne del compilatore che maschererebbero l’uso del move constructor (fate questo giusto come prova, però poi rimuovete quella flag!).</li>
</ul>
<h2 id="eccezioni-in-c">Eccezioni in C++</h2>
<p>Nei metodi della classe <code>Vettore</code> o nelle funzioni corrispondenti abbiamo spesso utilizzato la funzione <code>exit()</code> per interrompere l’esecuzione del programma in caso si incontri una condizione patologica (per esempio tentiamo di accedere ad una componenete che non esiste). Questo approccio non è considerato buon conding: in generale non vogliamo che il comportamento di una funzione (magari scritta da altri) possa decidere la sorte del programma. Sarebbe meglio che la funzione potesse fornire al <code>main</code> l’informazione su eventuali errori di esecuzione e lasciare al <code>main</code> la possibilità di decidere della sorte del programa. In C++ esiste un meccanismo di gestione delle <a href="https://cplusplus.com/doc/tutorial/exceptions/">eccezioni</a>. Per capire meglio come utilizzare le eccezioni in C++ proviamo a tenere come esempio il metodo di accesso ad un elemento (<code>GetComponent()</code>). Con la modifica seguente:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Vettore <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a> <span class="co">// ....</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">double</span> GetComponent<span class="op">(</span><span class="dt">int</span> k<span class="op">)</span> <span class="at">const</span> <span class="op">{</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="op">(</span>k <span class="op">></span> <span class="va">m_N</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a> <span class="cf">throw</span> <span class="dv">99</span><span class="op">;</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">m_v</span><span class="op">[</span>k<span class="op">];</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> <span class="va">m_N</span><span class="op">;</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a> <span class="dt">double</span> <span class="op">*</span><span class="va">m_v</span><span class="op">;</span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>il metodo <code>GetComponent()</code> può essere usato nel modo seguente dal <code>main()</code>:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">"Vettore.h"</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a> Vettore v<span class="op">(</span><span class="dv">3</span><span class="op">);</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a> v<span class="op">.</span>SetComponent<span class="op">(</span><span class="dv">1</span><span class="op">,</span> <span class="dv">99</span><span class="op">);</span></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a> v<span class="op">.</span>GetComponent<span class="op">(</span><span class="dv">4</span><span class="op">);</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="dt">int</span> errcode<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a> cout <span class="op"><<</span> <span class="st">"Error code "</span> <span class="op"><<</span> errcode <span class="op"><<</span> <span class="st">" exiting "</span> <span class="op"><<</span> endl<span class="op">;</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a> exit<span class="op">(</span><span class="dv">44</span><span class="op">);</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Come si può notare, quando si tenta di leggere la componente 4 (che non esiste) il metodo <code>GetComponent()</code> solleva un’eccezione che viene propagata al <code>main</code>. A questo punto si può decidere cosa fare direttamente nel <code>main()</code>.</p>
<h1 id="errori-comuni">Errori comuni</h1>
<p>Tra errori che gli studenti hanno fatto negli anni precedenti, ci sono ovviamente già quelli elencati per la <a href="carminati-esercizi-01.html#errori-comuni">prima lezione</a>. A questi se ne aggiungono i seguenti:</p>
<ul>
<li><p>Stranamente, molti studenti che avevano consegnato esercizi della lezione 1 con un calcolo corretto di media, mediana e varianza consegnano per la lezione 2 esercizi che calcolano quegli stessi valori in modo sbagliato!</p></li>
<li><p>È capitato più di una volta che gli esercizi di alcuni studenti che implementavano il <em>move constructor</em> non compilavano neppure. Questo ha lasciato basiti noi docenti: idealmente, <strong>tutti</strong> gli esercizi che si consegnano devono compilare senza errori… Se non riuscite a trovare la causa dell’errore, contattate i docenti prima di consegnare!</p></li>
</ul>
</main>
<script>
;(function() {
// Non-essential if user has JavaScript off. Just makes checkboxes look nicer.
var selector = '.task-list > li > input[type="checkbox"]';
var checkboxes = document.querySelectorAll(selector);
Array.from(checkboxes).forEach((checkbox) => {
var wasChecked = checkbox.checked;
checkbox.disabled = false;
checkbox.addEventListener('click', (ev) => {ev.target.checked = wasChecked});
});
})();
</script>
</body>
</html>