PDA

Visualizza la versione completa : [C++] Dichiarazione anticipata con classe template - problema


innaig86
26-09-2008, 12:17
Salve, ho un problema che vorrei esporvi. Ho fatto diverse prove e credo di aver individuato la causa.

Il codice questo:


#ifndef LISTA_PUNTATORI_H
#define LISTA_PUNTATORI_H



template <typename T> class Lista_puntatori {

// blocco di interesse---------------------
struct nodo {
T elemento;
nodo * successivo;
nodo * precedente;
};

typedef nodo * posizione;

//fine blocco di interesse------------------

public:

Lista_puntatori();
~Lista_puntatori();

void creaLista();
void insLista(T, posizione);
void scriviLista(T, posizione);
void cancLista(posizione);

bool listaVuota();
bool fineLista(posizione);

posizione primoLista();
posizione succLista(posizione);
posizione precLista(posizione);

T leggiLista(posizione);

private:
posizione primo;
};


template <class T> Lista_puntatori<T>::Lista_puntatori(){
creaLista();
};

template <class T> Lista_puntatori<T>::~Lista_puntatori(){
posizione p;
while (primo != NULL){
p = primo;
primo = primo->successivo;
delete p;
}
};

template <class T> void Lista_puntatori<T>::creaLista(){
primo = NULL;
};

template <class T> void Lista_puntatori<T>::insLista(T elem, posizione p){
posizione temp;
temp->elemento = elem;
temp->successivo = p;

if (primo == p){
temp->precedente = NULL;
primo = temp;
} else {
temp->precedente = p->precedente;
precLista(p)->successivo = temp;
p->precedente = temp;
}
};

template <class T> void Lista_puntatori<T>::scriviLista(T elem, posizione p){
if ((primo != NULL) && (p != NULL)){
p->elemento = elem;
}
};

template <class T> void Lista_puntatori<T>::cancLista(posizione p){
if ((p != NULL) && (primo != NULL)){
precLista(p)->successivo = p->successivo;
succLista(p)->precedente = p->precedente;
delete p;
}
};

template <class T> bool Lista_puntatori<T>::listaVuota(){
return (primo == NULL);
};


template <class T> bool Lista_puntatori<T>::fineLista(posizione p){
return (p == NULL);
};

template <class T> posizione Lista_puntatori<T>::primoLista(){
return primo;
};

template <class T> posizione Lista_puntatori<T>::succLista(posizione p){
if (p != NULL)
return p->successivo;
else
return NULL;
};

template <class T> posizione Lista_puntatori<T>::precLista(posizione p){
if (p != NULL)
return p->precedente;
else
return NULL;
};

template <class T> T Lista_puntatori<T>::leggiLista(posizione p){
if (p != NULL)
return p->elemento;
else
return NULL;
};

#endif


Il problema principale : in fase di compilazione, mi da errore "expected constructor, destructor, or type conversion before "Lista_puntatori"" e "expected ';' before "Lista_puntatori"" sulle righe 98, 102, e 108, che sono le implementazioni delle funzioni primoLista(), succLista() e precLista().

Per quanto ne ho capito, il problema deriva dalla definizione di "posizione" (infatti tutte quelle funzioni dovrebbero restituire un dato di tipo posizione).
La causa dovrebbe essere il fatto che nodo e posizione sono definiti dopo la dichiarazione della classe (dopo la 3a riga in pratica, commentato come "blocco di interesse"), mentre dovrebbero essere posizionati prima della 3a riga.

Per risolvere questo problema, ho provato a portare il "blocco di interesse" prima della 3a riga.
Il risultato che, giustamente, l non sa ancora cos' T (utilizzata nello struct) e quindi se provo in quest'altro modo d errore: 'T' does not name a type.


#ifndef LISTA_PUNTATORI_H
#define LISTA_PUNTATORI_H

// blocco di interesse---------------------
struct nodo {
T elemento;
nodo * successivo;
nodo * precedente;
};

typedef nodo * posizione;

//fine blocco di interesse------------------


template <typename T> class Lista_puntatori {

Per far conoscere T in quel punto, dovrei fare una dichiarazione anticipata della classe, ma anche se provo a fare:

#ifndef LISTA_PUNTATORI_H
#define LISTA_PUNTATORI_H
template <typename T> class Lista_puntatori;
// blocco di interesse---------------------
struct nodo {
T elemento;
nodo * successivo;
nodo * precedente;
};

typedef nodo * posizione;

//fine blocco di interesse------------------


template <typename T> class Lista_puntatori {

mi dice sempre 'T' does not name a type.

Ora, come potrei fare per far funzionare sto codice?
Avete qualche idea?

Grazie.

XWolverineX
26-09-2008, 12:27
Non puoi dichiarare la struttura dopo la classe?

innaig86
26-09-2008, 12:31
No, perch la variabile "posizione" un puntatore allo struct e viene utilizzato all'interno della classe.
Quindi ho bisogno di avere "posizione" subito.

ps: sono decisamente alle prime armi con c++. :(

shodan
26-09-2008, 13:18
Se non ho visto male c' una grafa di troppo:


template <typename T> class Lista_puntatori {
// blocco di interesse---------------------


Comunque io modificherei il codice in questo modo:




// blocco di interesse---------------------
template <typename U>
struct nodo {
nodo(nodo* n1=0,nodo* n2=0) : successivo(n1),precedente(n2) {} // azzera in automatico i puntatori.
U elemento;
nodo * successivo;
nodo * precedente;
};


//fine blocco di interesse------------------
template <typename T> class Lista_puntatori {

private:
typedef nodo<T>* posizione;
public:

Lista_puntatori();
~Lista_puntatori();

void creaLista();
void insLista(T, posizione);
void scriviLista(T, posizione);
void cancLista(posizione);

bool listaVuota();
bool fineLista(posizione);

posizione primoLista();
posizione succLista(posizione);
posizione precLista(posizione);

T leggiLista(posizione);

private:
posizione primo;
};

Poi ci sono errori concettuali nelle varie funzioni.
CreaLista inutile se serve ad azzerare solo un puntatore, per quello ci pu pensare il costruttore della classe, dovrebbe invece controllare se il puntatore allocato o no e nel caso non lo sia, allocare la memoria per "primo", se invece "primo" gi allocato dovrebbe resettare la lista precedente per crearne una nuova.

innaig86
26-09-2008, 13:42
Non ho capito come mai quella graffa sia di troppo.. quella di apertura della classe..

Comunque ho provato ad effettuare le modifiche che mi hai suggerito (grazie mille ;) ), ma niente, sempre lo stesso errore:

Linea 94 expected constructor, destructor, or type conversion before "Lista_puntatori"
Linea 94 expected ';' before "Lista_puntatori"
Linea 98 expected constructor, destructor, or type conversion before "Lista_puntatori"
Linea 98 expected ';' before "Lista_puntatori"
Linea 105 expected constructor, destructor, or type conversion before "Lista_puntatori"
Linea 105 expected ';' before "Lista_puntatori"

le linee sono le seguenti:

template <class T> bool Lista_puntatori<T>::fineLista(posizione p){
return (p == NULL);
};

template <class T> posizione Lista_puntatori<T>::primoLista(){ //linea 94
return primo;
};

template <class T> posizione Lista_puntatori<T>::succLista(posizione p){ //linea 98
if (p != NULL)
return p->successivo;
else
return NULL;
};

template <class T> posizione Lista_puntatori<T>::precLista(posizione p){ //linea 105
if (p != NULL)
return p->precedente;
else
return NULL;
};

PeppePes88
26-09-2008, 18:33
se le funzioni le metti all'interno della classe funziona tutto!! E' un problema di scope... ma purtroppo non riesco ad esserti di maggior aiuto..

PeppePes88
26-09-2008, 18:44
Ho trovato una soluzione ma non sono riuscito a capirla ::: Basta che nella definizione della funzione metti typename es :



#include <iostream>


template < class T> class Lista {

struct nodo {
nodo * next;
T info;
};

typedef nodo * nodo_ptr;

nodo_ptr list;

public:

Lista(){ list = NULL; };
~Lista();
Lista( const Lista&);

T first() { if(list->info) return list->info;};

nodo_ptr get();

};

template < class T >Lista<T>::~Lista() {

nodo_ptr temp = list;

while ( list) {
temp = list;
list = list->next;
delete temp;
}

list = NULL;

}


template < class T > typename
Lista<T>::nodo_ptr Lista<T>::get(){
return list;
}
;

shodan
26-09-2008, 20:06
Originariamente inviato da innaig86
Non ho capito come mai quella graffa sia di troppo.. quella di apertura della classe..

Pardon, ho visto male. :)

Per quanto riguarda il resto.
Quando si usa una nested class occorre specificare tutto il percorso del nome della variabile, come ha fatto PeppePes88. Il typename necessario (quando si usa un template) per specificare al compilatore che quello che segue non una variabile appartente alla classe ma un nome di tipo.

Loading