Newsgroup: it.comp.lang.c++
Titolo: un' altro problema di const

/* Dichiarazioni: */
bool isempty(const Record* &L);		
void append(Record* &L, int e);
 
 
/* Definizioni*/
bool isempty(const Record* &L)	
{
     if (L == 0)
     return true;
     else
     return false;
}
 
 
//----------------
 
 
void append(Record* &L, int e)
{
 
 
45.     if (isempty(L) == true)   /* <<<<<<<< qui sta l'errore che ho scritto piu' in basso */
     {
 
                    push(L, e); 
                    return;
 
     }
 
 
     //creo il nodo
     Record* q = new Record; 
 
     q->elem = e; 
     q->next = 0; 
 
 
    Record* temp = L; 
    while(temp->next != 0) temp = temp->next; 
    temp->next = q;  
 
 
}
 
--------
 
 
 
 
errore: 45  invalid initialization of reference of type 'const Record*&' from expression of type 'Record*' 
 
 
come mai ricevo l'errore? da quel che ho letto quel cast "implicito" è permesso! ... l'inverso dovrebbe dare l'errore .
Fatemi sapere, grazie ;)

 
 
Sarebbe permesso se isempty accettasse un "Record* const& L".
Devi pensare a *cosa* rimane costante!
Ciao!


 
Consiglierei all' amico di iniziare a ragionare per classi
Visto che il primo parametro delle funzioni scritte � un Record*,
trasformare quel Record* in classe e le funzioni in metodi
 

 trasformare quel Record* in classe e le funzioni in metodi
 
Più che altro di fare un po' di chiarezza nella sintassi, visto che in questo
caso non vedo motivo per non passare semplicemente un puntatore alle due
funzioni (ovviamente ragionando a classi tutto di guadagnato, il problema in
oggetto non si porrebbe proprio).
Ciao!

 Fatemi sapere, grazie ;)
 
 
-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
 

si, la ragione c'e'. E' per mantere la stessa interfaccia di un programma che sostanzialmente fa le stesse cose ma in modo diversa. Quindi è semplicemente per mantenere la stessa interfaccia di un'altra cosa.


anche se penso a ciò che deve rimanere costante ... perchè in questo modo facendo mi viene restituito un errore?

 facendo mi viene restituito un errore?
 
Spero che l'esempio sotto sia esplicativo, ma ne puoi trovare di simili se
cerchi l'argomento.. seguilo passo passo:
 
const char s_str[] = "Stringa costante";
void func1(const char*& s)
{
    s = s_str;    /* si può fare, ovviamente */
}
int func2()
{
  char* p;
  func1(p);   /* quello che provi a fare te, se si potesse fare.. */
  p[0] = 'A'; /* BAM! modifichi una stringa costante! */
}
 
Ciao!


quindi, nel tuo esempio, mettendo la func1 come:
 
void func1( char* const &s)
 
mi accerterei che l' "alias" s sia immodificabile e non dovrei avere errori. dico bene?

 mi accerterei che l' "alias" s sia immodificabile e non dovrei avere errori.. dico bene?


anche io farei un semplice passaggio per valore. Ma questo esercizio è per didattica. Stiamo sviluppando le liste fatte in diversi modi (utilizzo di array o di linked list con strutture allocate dinamicamente). Per mantenere la stessa interfaccia di implementazione tra i due modi di operare la professoressa ha messo un reference anche laddove era "praticamente" superfluo. Oggi sono andato a ricevimento e mi ha detto cosi' XD ... infatti anche ma la cosa sembrava strano. 
E' chiaro che poi laddove si ha la necessità di modificare l'head_pointer originale della lista utilizzerei un passaggio per riferimento (e di certo non ci metterei la const). A mio parere, per fare sto "giochetto" di mantenere la stessa interfaccia, la professoressa si è complicata non poco, anche se c'e' da dire che lei nel suo codice utilizza typedef a tutto spiano ! Utilizzando i typedef i problemi di cui sopra non si pongono. 
 
un saluto 


Donne e puntatori, son gioie e dolori! :)
Scherzi a parte, evidentemente neanche la tua professoressa ha dimestichezza
con il C++. I typedef, poi, i problemi li complicano, non li risolvono: te li
fanno solo scrivere in meno codice.
Se non ti risulta ancora il perché dei nostri dubbi, vedila così: la reference
è la stessa identica cosa di puntatore (a parte due/tre cosette abbastanza
importanti ma che non rientrano in questo discorso), quindi dove hai un
Record*& è come avessi un Record**. Evidentemente non solo è inutile, ma anche
più difficile!
Ciao!

 un saluto


 
 
 
Ringrazio tutte per le risposte e "Donne e puntatori, son gioie e dolori! :)" mi ha fatto morir dal ridere XD.
Cmq il fatto che con i typedef vengono nascosti i problemi non è proprio vero, nel senso che la professoressa ha fatto dinanzi a me delle cose di questo tipo
typedef Record* PTR ed è andata a sostituire PTR in ogni funzione (al posto di Record*). Il compilatore non dava piu' errori:
la sua spiegazione a tale "fenomeno" è stata piu' o meno questa: " con il typedef è come se avessi definito un tipo a parte e quindi la const che si trova nella dichiarazione\definizione non ha ambiguità. Viene sempre associata al puntatore L (la lista) e non all'oggetto puntato. E' come se mi avesse in un certo ugual senso messo delle parentesi a Record* e fatto in modo che quella const si riferisse alla lista e non all'oggetto di tipo Record puntato Quindi avendo eliminato questa ambiguità il compilatore non mi fornisce piu' l'errore." a questo la proff. ha aggiunto : "devi considerare la reference come un TIPO" (e a questo punto mi sono sorte altre 23423 miliardi di domande). Che io sappia la reference non è un tipo ma un semplice alias. Mi indica la cella di memoria della variabile passata e dereferenziata direttamente; ma da qui a dire che è un TIPO la vedo dura (forse mi confondo io ma non ho mai letto in giro una cosa del genere). 
 
Un saluto ;)
 
 


 
No no no, aspetta... non è proprio giusta 'sta cosa.
 
Il reference alla C++ è, per il programmatore, né più né meno di un puntatore
con certe restrizioni (non può essere NULL, non può essere riassegnato, etc.).
Si usa di solito perché rende il codice più leggibile e ti elimina errori
classici del C come deferenziare puntatori NULL o puntatori ad un oggetto non
più in vita (pensa ad una funzione che ritorna un puntatore ad un oggetto
locale).
 
Sul fatto che i typedef creano un tipo è ovviamente vero, ma è nè più nè meno
che mettere delle parentesi per rendere la sintassi più leggibile: di solito
è praticamente l'unico modo per non incontrare roba come:
char *(*fnptr)(int[4], (void(*fnp2)(void*)))
e ci sono andato leggero (con i template i tipi possono diventare un chilometro
di roba senza neppure accorgersene, non è inusuale ad esempio che mischiando
vari container STL si raggiunga la lunghezza massima dei nomi di funzione).
 
Creare un tipo, a livello di compilatore, significa solo aggiungere un token
al parser che verrà comunque risostituito con l'espansione reale in fase di
compilazione: quindi è solo "syntactic sugar" (così come del resto lo sono i
reference, stiracchiando un po' il modo di dire).
 
Quindi nulla, se con i typedef riesci a compilare e senza no significa
solamente che non conosci le precedenze delle keywords! ;)
 
Ciao!

 Ciao!
 
E' ciò che ho pensato anche io ... ma vabbè XD  ... penso che riscriverò il programma come l'avrei scritto io e in base ai vostri consigli senza const e reference "superflui" e senza migliaia di typedef (per ora non ne vedo il vantaggio... per quanto mi riguarda mi confondono solo). Intanto vi ringrazio. Spero vivamente di poter trovare altri eventuali chiarimenti futuri in questo gruppo.
 
 
Ciao uaju' ;)