mirror of https://github.com/xfarrow/lasd.git
Lezione 5
This commit is contained in:
parent
a0fc2e6e6d
commit
bfc9b6ecd3
Binary file not shown.
|
@ -0,0 +1,51 @@
|
|||
#include<iostream>
|
||||
using namespace std;
|
||||
class A{
|
||||
public:
|
||||
int x;
|
||||
A(){
|
||||
cout<<"Sono nel costruttore di A"<<endl;
|
||||
x = x+1;
|
||||
}
|
||||
A(const A& a){
|
||||
cout<<"Sono nel costruttore di copia di A"<<endl;
|
||||
}
|
||||
};
|
||||
class B:public A{
|
||||
public:
|
||||
B(){
|
||||
cout<<"Sono nel costruttore di B"<<endl;
|
||||
x+=100;
|
||||
}
|
||||
B(const B& b){
|
||||
cout<<"Sono nel costruttore di copia di B"<<endl;
|
||||
}
|
||||
};
|
||||
class C:public B{
|
||||
public:
|
||||
C(){
|
||||
cout<<"Sono nel costruttore di C"<<endl;
|
||||
x+=1000;
|
||||
}
|
||||
C(const C& c){
|
||||
cout<<"Sono nel costruttore di copia di C"<<endl;
|
||||
}
|
||||
};
|
||||
int main(){
|
||||
/*
|
||||
Sono nel costruttore di A
|
||||
Sono nel costruttore di B
|
||||
Sono nel costruttore di C
|
||||
*/
|
||||
C obj;
|
||||
|
||||
cout<<endl;
|
||||
|
||||
/*
|
||||
Sono nel costruttore di A
|
||||
Sono nel costruttore di B
|
||||
Sono nel costruttore DI COPIA di C
|
||||
*/
|
||||
C obj2(obj);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
void problema();
|
||||
void soluzione();
|
||||
|
||||
int main(){
|
||||
//problema();
|
||||
soluzione();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void problema(){
|
||||
class A{
|
||||
public:
|
||||
int* v = new int[10];
|
||||
~A(){
|
||||
cout<<"Richiamato distuttore di A"<<endl;
|
||||
delete[] v;
|
||||
}
|
||||
};
|
||||
class B: public A{
|
||||
public:
|
||||
char* s = new char[20];
|
||||
~B(){
|
||||
cout<<"Richiamato distruttore di B"<<endl;
|
||||
delete[] s;
|
||||
}
|
||||
};
|
||||
|
||||
A* ptr = new B(); //dato che B è anche un tipo A, questo può essere fatto.
|
||||
delete ptr; // "Richiamato distruttore di A"
|
||||
/*
|
||||
Creo un oggetto B (quindi che contiene anche A) e lo assegno a un puntatore
|
||||
a oggetto A.
|
||||
Se poi faccio "delete ptr" il compilatore va a richiamare il distruttore di A
|
||||
e non anche quello di B. Quindi l'array di char "s" rimarrà in memoria almeno
|
||||
fino al termine del programma.
|
||||
*/
|
||||
}
|
||||
|
||||
void soluzione(){
|
||||
class A{
|
||||
public:
|
||||
int* v = new int[10];
|
||||
/*
|
||||
Virtual functions ensure that the correct function is called for an object,
|
||||
regardless of the type of reference (or pointer) used for function call.
|
||||
https://www.geeksforgeeks.org/virtual-function-cpp/
|
||||
*/
|
||||
virtual ~A(){ // metodo virtuale. Deve essere sempre fatto così sui distruttori.
|
||||
cout<<"Richiamato distuttore di A"<<endl;
|
||||
delete[] v;
|
||||
}
|
||||
};
|
||||
class B: public A{
|
||||
public:
|
||||
char* s = new char[20];
|
||||
~B(){
|
||||
cout<<"Richiamato distruttore di B"<<endl;
|
||||
delete[] s;
|
||||
}
|
||||
};
|
||||
A* ptr = new B(); //dato che B è anche un tipo A, questo può essere fatto.
|
||||
delete ptr; // "Richiamato distruttore di B Richiamato distuttore di A"
|
||||
}
|
|
@ -10,5 +10,41 @@
|
|||
= 0: pure virtual. A questo livello l'implementazione di questo metodo non esiste
|
||||
= default: ammesso solo per cost. e dist. che dice di creare quelli di default
|
||||
=delete: elimina un metodo precedentemente scritto nella gerarchia
|
||||
|
||||
*/
|
||||
/*
|
||||
Il corpo di una funzione può essere messo anche fuori dalla classe:
|
||||
*/
|
||||
#include<iostream>
|
||||
class ClassName{
|
||||
private:
|
||||
int y = 5;
|
||||
public:
|
||||
int x = 3;
|
||||
|
||||
int aggiungiX(int); // dichiarazione funzione
|
||||
|
||||
int aggiungiY(int); // dichiarazione funzione
|
||||
friend int aggiungiY(int); // dichiarazione friendship
|
||||
};
|
||||
/*
|
||||
NB: in questo caso x deve essere dichiarata pubblica. Se fosse stato un metodo
|
||||
all'interno della classe allora avrebbe potuto avere accesso anche se x
|
||||
fosse stata privata
|
||||
*/
|
||||
int ClassName::aggiungiX(int parametro){
|
||||
x+=parametro;
|
||||
}
|
||||
/*
|
||||
Oppure si può dichiarare la friendship per accedere a variabili private/protette
|
||||
*/
|
||||
int ClassName::aggiungiY(int parametro){
|
||||
y+=parametro;
|
||||
std::cout<<y<<std::endl;
|
||||
}
|
||||
int main(){
|
||||
ClassName obj;
|
||||
obj.aggiungiX(7);
|
||||
obj.aggiungiY(9);
|
||||
std::cout<<obj.x<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
ereditarietà a diamante:
|
||||
A <-- B
|
||||
A <-- C
|
||||
B <-- D
|
||||
C <-- D
|
||||
*/
|
||||
|
||||
class A{
|
||||
public:
|
||||
int a;
|
||||
A(){
|
||||
cout<<"A created"<<endl;
|
||||
}
|
||||
~A(){
|
||||
cout<<"A destroyed"<<endl;
|
||||
}
|
||||
};
|
||||
|
||||
class B : A{
|
||||
public:
|
||||
int b;
|
||||
B(){
|
||||
cout<<"B created"<<endl;
|
||||
}
|
||||
~B(){
|
||||
cout<<"B destroyed"<<endl;
|
||||
}
|
||||
};
|
||||
|
||||
class C : A{
|
||||
public:
|
||||
int c;
|
||||
C(){
|
||||
cout<<"C created"<<endl;
|
||||
}
|
||||
~C(){
|
||||
cout<<"C destroyed"<<endl;
|
||||
}
|
||||
};
|
||||
|
||||
class D : B,C{
|
||||
public:
|
||||
int d;
|
||||
D(){
|
||||
cout<<"D created"<<endl;
|
||||
}
|
||||
~D(){
|
||||
cout<<"D destroyed"<<endl;
|
||||
}
|
||||
};
|
||||
|
||||
int main(){
|
||||
/*
|
||||
Ogni oggetto deve avere all'interno gli oggetti ereditati. Quindi stampa:
|
||||
A created (per creare D mi serve prima B. Per creare B mi serve prima A)
|
||||
B created (creato A, posso creare B)
|
||||
A created (per creare D mi serve prima C. Per creare C mi serve prima A)
|
||||
C created (creato A, posso creare C)
|
||||
D created (creato B che contiene A e creato C che contiene A, posso creare D)
|
||||
*/
|
||||
D obj;
|
||||
cout<<endl;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
La distruzione viene effettuata al contrario
|
||||
D destroyed
|
||||
C destroyed
|
||||
A destroyed
|
||||
B destroyed
|
||||
A destroyed
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
#include<iostream>
|
||||
using namespace std;
|
||||
/*
|
||||
ereditarietà a diamante:
|
||||
A <-- B
|
||||
A <-- C
|
||||
B <-- D
|
||||
C <-- D
|
||||
*/
|
||||
|
||||
void nonVirtualInheritance();
|
||||
void virtualInheritance();
|
||||
int main(){
|
||||
//nonVirtualInheritance();
|
||||
virtualInheritance();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nonVirtualInheritance(){
|
||||
class A{
|
||||
public:
|
||||
int size = 7;
|
||||
};
|
||||
|
||||
class B : public A{
|
||||
public:
|
||||
int b;
|
||||
};
|
||||
|
||||
class C : public A{
|
||||
public:
|
||||
int c;
|
||||
};
|
||||
|
||||
class D : public B, public C{
|
||||
public:
|
||||
int d;
|
||||
};
|
||||
|
||||
/*
|
||||
Adesso B ha una copia di A, C ha una copia di A, D ha una copia di B e una
|
||||
copia di C. Implica che D ha due copie di A.
|
||||
Se provo a stampare size, cosa succede?
|
||||
*/
|
||||
D obj;
|
||||
//cout<<obj.size<<endl; //request for member ‘size’ is ambiguous
|
||||
|
||||
cout<<obj.B::size<<endl;
|
||||
cout<<obj.C::size<<endl;
|
||||
}
|
||||
|
||||
void virtualInheritance(){
|
||||
class A{
|
||||
public:
|
||||
int size = 7;
|
||||
};
|
||||
|
||||
class B : virtual public A{
|
||||
public:
|
||||
int b;
|
||||
};
|
||||
|
||||
class C :virtual public A{
|
||||
public:
|
||||
int c;
|
||||
};
|
||||
|
||||
class D : public B, public C{
|
||||
public:
|
||||
int d;
|
||||
};
|
||||
|
||||
D obj;
|
||||
cout<<obj.size; // adesso posso stampare tranquillamente size
|
||||
|
||||
/*
|
||||
Questo è possibile grazie al fatto che B e C ereditano A in modo virtuale,
|
||||
ovverosia, c'è solo un'istanza A condivisa tra B e C.
|
||||
https://www.cprogramming.com/tutorial/virtual_inheritance.html
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#include<iostream>
|
||||
using namespace std;
|
||||
class A{
|
||||
private:
|
||||
int a = 1;
|
||||
protected:
|
||||
int b = 2;
|
||||
public:
|
||||
int c = 3;
|
||||
int sameVariable = 4;
|
||||
};
|
||||
|
||||
class B : A{
|
||||
public:
|
||||
int sameVariable = 9;
|
||||
void test(){
|
||||
//cout<<a<<endl; // errore, "a" è privata
|
||||
cout<<b<<endl; // 2
|
||||
cout<<c<<endl; // 3
|
||||
cout<<sameVariable<<endl; // 9
|
||||
}
|
||||
};
|
||||
|
||||
int main(){
|
||||
B b;
|
||||
b.test();
|
||||
//cout<<b.a<<endl; //NO
|
||||
//cout<<b.b<<endl; //NO
|
||||
|
||||
/*
|
||||
Benché A::c sia pubblica, non posso accedergli da qua perché di default
|
||||
l'ereditarietà viene fatta in modo privato.
|
||||
Se avessi scritto class B:public A allora avrei potuto stampare.
|
||||
*/
|
||||
//cout<<b.c<<endl; //NO
|
||||
cout<<b.sameVariable<<endl; // 9
|
||||
|
||||
/*
|
||||
Se l'ereditarietà fosse stata pubblica (B: public A) avrei potuto scrivere
|
||||
cout<<b.A::sameVariable<<endl;
|
||||
per eccedere a "sameVariable" di A
|
||||
*/
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue