Salve ragazzi, sono nuovo con la programmazione ad oggetti e soppratutto non riesco a stare dietro ad un mio prof che da troppe cose per scontate.
Questo prof ci ha mostrato (velocemente e male) come creare una classe astratta "LinearList" e successivamente specializzarla creando un'altra classe che utilizza i vettori come rappresentazione della lista. Fin qui tutto bene, il punto è che non ho capito bene l'utilizzo della parola typename.
So che sarà un dubbio stupido ma non sono riuscito a venirne a capo da solo.
La classe astratta è questa:
template<class T, class P>
class LinearList {
public:
typedef T value_type; //alias, rinomino il tipo generico T
typedef P position; //alias, rinomino il tipo generico P
//Metodi virtuali
virtual void create() = 0;
virtual bool empty() const = 0;
virtual value_type read(position p) const = 0;
virtual void write(const value_type &elemento, position p) = 0;
virtual position begin() const = 0;
virtual bool end(position p) const = 0;
virtual position next(position) const = 0;
virtual position previous(position) const = 0;
virtual void insert(const value_type &x, position p) = 0;
virtual void erase(position p) = 0;
};
La specializzazione invece è questa:
template<class T>
class ListVector : public LinearList<T, int> {
public:
typedef typename LinearList<T, int>::value_type value_type;
typedef typename LinearList<T, int>::position position;
//Costruttori e Distruttore
ListVector();
ListVector(int dimensione);
ListVector(const ListVector<T>& altro);
~ListVector();
//Diamo una realizzazione ai metodi virtuali presenti nella classe astratta LinearList
void create();
bool empty() const;
value_type read(position p) const;
void write(const value_type &elemento, position p);
position begin() const;
bool end(position p) const;
position next(position p) const;
position previous(position p) const;
void insert(const value_type &x, position p);
void erase(position p);
private:
int lunghezza;
int dimensioneArray;
value_type* elementi;
void cambiaDimensione(T*& array, int vecchiaDimensione, int nuovaDimensione);
};
template<class T>
ListVector<T>::ListVector(){
dimensioneArray = 10;
this->create();
}
template<class T>
ListVector<T>::ListVector(int dimensione){
dimensioneArray = dimensione;
this->create();
}
template<class T>
ListVector<T>::ListVector(const ListVector<T>& altro){
this->dimensioneArray = altro.dimensioneArray;
this->lunghezza = altro.lunghezza;
this->elementi = new T[dimensioneArray];
for(int i=0; i<dimensioneArray; i++)
this->elementi[i] = altro.elementi[i];
}
template<class T>
ListVector<T>::~ListVector(){
delete elementi;
}
template<class T>
void ListVector<T>::create(){
this->elementi = new T[dimensioneArray];
this->lunghezza = 0;
}
template<class T>
bool ListVector<T>::empty() const{
return(lunghezza == 0);
}
//Nel caso non è rispettata la precondizione che ritorna??
template<class T>
typename ListVector<T>::value_type ListVector<T>::read(position p) const{
if((p > 0) && (p < lunghezza + 1))
return(elementi[p-1]);
}
template<class T>
void ListVector<T>::write(const value_type &elemento, position p){
if((p>0) && (p<lunghezza+1))
elementi[p-1] = elemento;
}
template<class T>
typename ListVector<T>::position ListVector<T>::begin() const{
return(1);
}
template<class T>
bool ListVector<T>::end(position p) const{
if ((p > 0) && (p <= lunghezza + 1))
return( p == lunghezza + 1);
else
return(false);
}
template<class T>
typename ListVector<T>::position ListVector<T>::next(position p) const{
if ((p > 0) && (p < lunghezza + 1))
return(p+1);
else
return(p);
}
template<class T>
typename ListVector<T>::position ListVector<T>::previous(position p) const{
if ((p > 1) && (p < lunghezza + 1))
return(p-1);
else
return(p);
}
template<class T>
void ListVector<T>::insert(const value_type &a, position p){
if (lunghezza == dimensioneArray){
cambiaDimensione(elementi, dimensioneArray, dimensioneArray * 2);
dimensioneArray = dimensioneArray * 2;
}
if ((p > 0) && (p <= lunghezza + 1)) {
for (int i=lunghezza; i >= p; i--){
elementi[i] = elementi[i-1];
}
elementi[p-1]=a;
lunghezza++;
}
}
template<class T>
void ListVector<T>::cambiaDimensione(T*& array, int vecchiaDimensione, int nuovaDimensione){
T* temp = new T[nuovaDimensione];
int numero;
if (vecchiaDimensione < nuovaDimensione)
numero = vecchiaDimensione;
else
numero = nuovaDimensione;
for (int i=0; i<numero; i++)
temp[i] = array[i];
delete [] array;
array = temp;
}
template<class T>
void ListVector<T>::erase(position p){
if ( (p > 0) && ( p < lunghezza + 1)) // precondizione
if (!empty()) {
for (int i=p-1; i<(lunghezza-1); i++)
elementi[i] = elementi[i+1];
lunghezza--;
}
}
La parte di codice che non ho capito bene è questa:
template<class T>
typename ListVector<T>::value_type ListVector<T>::read(position p) const{
if((p > 0) && (p < lunghezza + 1))
return(elementi[p-1]);
}
I miei dubbi sono:
1 - Cosa sta ad indicare quel "typename ListVector<T>::value_type ListVector<T>:: ..." nell'intestazione della funzione? Come dovrei leggerlo?. Ho capito che il "typename" serve ad indicare al compilatore che stiamo lavorando con un determinato tipo ma non capisco cosa stiamo dicendo al compilatore scrivendo così.
2 - La funzione "read" sopra è vincolata da un if, nel caso l'if non si verifica cosa restituisce?