Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    Passaggio di un indirizzo per reference [C++]

    Ho implementato la il tipo di dato lista concatenata in c++. Solo che in un metodo della classe Lista<T> mi da errore quando passo un indirizzo a nodo.
    Mi spiego meglio

    codice:
    #ifndef NODO_H
    #define NODO_H
    
    #include <iostream>
    using namespace std;
    
    template <class T>
    class Nodo{
    public:
    	Nodo(){
    		info = 0;
    		ps = 0;
    	}
    
    	Nodo(const T& x,Nodo* p = NULL){
    		info = x;
    		ps = p;
    	}
    	Nodo(const Nodo& n){  
    		info = n.info;
    		ps = n.ps;
    	}
    
    	void setInfo(const T& x){
    		info = x;
    	}
    
    	void setPs(const Nodo* &p){  //mi da errore con void setPs(const Nodo* &p)
    		ps = p;
    	}
    
    	T getInfo(){
    		return info;
    	}
    
    	Nodo* getPs(){
    		return ps;
    	}
    
    
    private:
    	T info;
    	Nodo *ps;
    };
    
    #endif
    Come potete vedere con setPs passo un indirizzo e lo passo per reference costante per prevenire modifiche.

    codice:
    //Lista.h
    #include <iostream>
    #include <assert.h>
    #include "Nodo.h"
    using namespace std;
    
    template <class T>
    class Lista{
    public:
    	Lista();
    	Lista(const Lista&);
    	~Lista();
    
    	bool inserisciInTesta(const T&);
    	bool inserisciInCoda(const T&);
    	bool inserisciPostoI(const T&,int i);
    
    	bool rimuoviInTesta(T&);
    	bool rimuoviInCoda(T&);
    	bool rimuoviPostoI(T&);
    
    	T getInfoPostoI(int i);
    
    	int getDim();
    
    private:
    	Nodo<T> *testa;
    	int dim;
    };
    
    template <class T>
    bool Lista<T>::inserisciInTesta(const T& x){
    	Nodo<T> *nuovo;
    	nuovo = new (nothrow) Nodo<T>;
    	if(nuovo == NULL)
    		return false;
    	dim++;
    	nuovo->setInfo(x);
    	nuovo->setPs(testa);
    	testa = nuovo;
    	return true;
    }
    
    template <class T>
    bool Lista<T>::inserisciInCoda(const T& x){
    	Nodo<T> *current = testa,*nuovo;
    	nuovo = new (nothrow) Nodo<T>;
    	if(nuovo == NULL)
    		return false;
    	nuovo->setInfo(x);
    	nuovo->setPs(NULL);
    	dim++;
    	if(testa == NULL){
    		testa = nuovo;
    	}
    	else{
    		while(current->getPs() != NULL)
    			current = current->getPs();
    		current->setPs(nuovo);
    	}
    	return true;
    }
    
    template <class T>
    bool Lista<T>::inserisciPostoI(const T& x,int i){
    	Nodo<T> *current = testa,*nuovo;
    	if(i<=0 || i>dim)
    		return false;
    	nuovo = new (nothrow) Nodo<T>;
    	if(nuovo == NULL)
    		return false;
    	if(i==1){
    		inserisciInTesta(x);
    	}
    	else{
    		for(int j=1;j<i-1;j++){
    			current = current->getPs();
    		}
    		nuovo->setInfo(x);
    		nuovo->setPs(current->getPs());
    		current->setPs(nuovo);
    		dim++;
    	}
    	return true;
    }
    			
    
    template <class T>
    int Lista<T>::getDim(){
    	return dim;
    }
    
    template <class T>
    Lista<T>::Lista(){
    	dim = 0;
    	testa = NULL;
    }
    
    template <class T>
    Lista<T>::Lista(const Lista& x){
    	int dim = x.getDim();
    	Nodo<T> *n1 = x.testa;
    	Nodo<T> *nuovo,*current;
    	if(dim>=1){
    		nuovo = new Nodo;
    		nuovo->setInfo(x.testa->getInfo());
    		testa = nuovo;
    		current = nuovo;
    		n1 = n1->getPs();
    		for(int i=2;i<=dim;i++){
    			nuovo = new Nodo;
    			nuovo->setInfo(n1->getInfo());
    			current.setPs(nuovo);
    			current = nuovo;
    			n1 = n1->getPs();
    		}
    		current->setPs(NULL);
    	}
    }
    
    template <class T>
    Lista<T>::~Lista(){
    	Nodo<T> *temp;
    	Nodo<T> *current = testa;
    	for(int i=1;i<=getDim();i++){
    		temp = current->getPs();
    		delete current;
    		current = temp;
    	}
    }
    e qui il compilatore mi da degli errori:

    codice:
    Errore	1	error C2664: 'Nodo<T>::setPs': impossibile convertire il parametro 1 da 'Nodo<T> *' a 'const Nodo<T> *&'	d:\documents and settings\vincenzo\documenti\visual studio 2008\projects\pilallcpp\pilallcpp\lista.h	41	PilaLLCpp
    Errore	2	error C2664: 'Nodo<T>::setPs': impossibile convertire il parametro 1 da 'int' a 'const Nodo<T> *&'	d:\documents and settings\vincenzo\documenti\visual studio 2008\projects\pilallcpp\pilallcpp\lista.h	53	PilaLLCpp
    Errore	3	error C2664: 'Nodo<T>::setPs': impossibile convertire il parametro 1 da 'Nodo<T> *' a 'const Nodo<T> *&'	d:\documents and settings\vincenzo\documenti\visual studio 2008\projects\pilallcpp\pilallcpp\lista.h	61	PilaLLCpp
    Errore	4	error C2664: 'Nodo<T>::setPs': impossibile convertire il parametro 1 da 'Nodo<T> *' a 'const Nodo<T> *&'	d:\documents and settings\vincenzo\documenti\visual studio 2008\projects\pilallcpp\pilallcpp\lista.h	82	PilaLLCpp
    Errore	5	error C2664: 'Nodo<T>::setPs': impossibile convertire il parametro 1 da 'Nodo<T> *' a 'const Nodo<T> *&'	d:\documents and settings\vincenzo\documenti\visual studio 2008\projects\pilallcpp\pilallcpp\lista.h	83	PilaLLCpp
    Che cavolo significa che non riesce a convertire un Nodo<T>* in un Nodo<T>*&?
    Il secondo errore è dovuto al fatto che alla riga 53 gli passo NULL, ma non capisco perchè mi da errore...

    codice:
    //main
    #include "Nodo.h"
    #include "Lista.h"
    #include <iostream>
    using namespace std;
    
    int main(){
    	Lista<int> l;
    	l.inserisciInTesta(2);
    	l.inserisciInTesta(4);
    	l.inserisciInCoda(20);
    	l.inserisciPostoI(52,2);
    	system("pause");
    	return 0;
    }

  2. #2
    In Nodo.h ( dove si trova il problema) ho provato a fare:
    void setPs( Nodo* const p); Praticamente ho dichiarato un puntatore costante a dati non costanti, ma io lo volevo costante a dati costanti. In parole povere, siccome l'oggetto Nodo passato per indirizzo è di sola lettura, volevo utilizzare const, come di solito si fa per le variabili di sola lettura, per esempio

    void prova(const int& t); t posso solo leggerlo, non dovrebbe essere la stessa cosa se al posto di int ci metto int*, e in particolare Nodo<T>*?

  3. #3
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    La sintassi corretta è:
    codice:
    	void setPs(const Nodo* const& p ) {
               // però qui serve il const_cast altrimenti da errore sull'assegnazione. 
    		ps = const_cast<Nodo*>(p);
    	}
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  4. #4
    Originariamente inviato da shodan
    La sintassi corretta è:
    codice:
    	void setPs(const Nodo* const& p ) {
               // però qui serve il const_cast altrimenti da errore sull'assegnazione. 
    		ps = const_cast<Nodo*>(p);
    	}
    Anzitutto, grazie per la risposta.
    Me lo puoi spiegare meglio? Cioè, se Nodo<T>* è il tipo di dato che sto passando alla funzione, non dovrebbe essere corretto fare const Nodo<T>* &n ?
    Quando uso i reference, praticamente è come usare la variabile originale, cioè per esempio, passandolo per puntatore ti devi ricordare di usare la freccia, in C++ con i reference no. Perchè devo fare il cast? Cioè io i reference costanti li ho sempre usati normalmente senza tenere conto che sono costanti. Sono un pò confuso

  5. #5
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Confesso che nemmeno io l'ho compreso appieno, però inizio a racappezzarmi.
    Dunque (leggendo da destra a sinistra):

    const int* p significa: p è un puntatore a un int costante, quindi si può cambiare dove punta p ma non il valore della variabile a cui punta.
    codice:
    int i=10;
    int j = 1000;
    const int* p = &i;
    *p = 20; // illegale
    p = &j; // ok
    int* const p significa: p è puntatore costante a un int, quindi non si può cambiare dove punta p ma si può cambiare il valore della variabile a cui punta.
    codice:
    int i=10;
    int j = 1000;
    int* const p = &i;
    *p = 20; // ok
    p = &j; // illegale
    const int* const p significa: p è puntatore costante a un int costante, quindi non si può cambiare dove punta p, ne si può cambiare il valore della variabile a cui punta.
    codice:
    int i=10;
    int j = 1000;
    const int* const p = &i;
    *p = 20; // ok
    p = &j; // illegale
    Alla luce di questo, mi sono accorto che la & finale di const int* const& p non serve a niente.

    Il compilatore poi non può permette l'assegnazione a un int* di un const int* const per cui serve il const_cast appunto.
    Fosse stato un oggetto e non un puntatore non c'erano problemi, visto che viene fatta una copia dell'oggetto e non assegnato un indirizzo.

    Sostituisci int* con Nodo* (o Nodo<T>* dove serve) e sei a posto.

    Per quanto riguarda il resto.
    Non ho trovato spiegazioni sul perché const int*& p non compili.
    Penso comunque dipenda dal fatto che, metaforicamente, uno voglia girare a destra, l'altro a sinistra e alla fine vadano a sbattere dritti contro il compilatore.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.