Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1

    [c++]Problemi con classi template di strutture dinamiche lineari

    Salve, da qualche giorno sto sviluppando alcuni template sulle strutture dinamiche lineari come le code, le pile e le liste.

    Nel corso dello sviluppo mi sono accorto di diversi problemi nella scrittura del codice. Più che altro di tipo teorico perchè credevo di aver fatto bene, ma poi dopo qualche suggerimento mi rendo conto che i miei sono errori di fondo.

    Non posto l'intero codice della mia lista altrimenti sarebbe lungo, ma scrivero vari snippet per risolvere un problema alla volta.

    La prima domanda che vi pongo è sull'uso degli iteratori, non c'è dubbio che siano di grande utilita, per quel che ho imparato so che è un puntatore per l'accesso agli elementi di un oggetto che contiene altri oggetti. Ora per sviluppare una lista ho implementato un iteratore molto semplice che però non riesco a compilare per via di un problema con la clausola friend.

    Vi posto il codice dell'interfaccia:
    codice:
    template<class T>
    class iterator
    {
        private:
           nodo<T>* pos;//classe template nodo
        public:
           iterator();
           iterator<T> &operator=(const iterator<T>&);
           void operator++();
           void operator--();
           friend class list<T>;//Classe template lista
    };
    Quando provo a richiamare nel main un iterator<int> i; mi da un errore su friend class list<T> riportando 'list' is not a template...

    Secondo voi cosa può essere? é inoltre la definizione di un iteratore in questo modo è corretta?

  2. #2
    Ho risolto da solo, la sintassi corretta per dichiarare la classe friend con la classe template, all'interno di una classe template era questa:

    template <class> friend class Nome_classe_template;

    A questo punto vi chiedo un ulteriore aiuto, più che altro dal punto di vista teorico.
    Se io dichiaro una classe template, nel mio caso lo stack, nel seguente modo:
    codice:
    template<class T> 
    class stak{
    ...
    private:
          nodo<T> *testa;
    public: void push(T const&);
    ...
    };
    
    template <class T>
    void stack<T>::push(T const& dato){
        nodo<T>* nuovo=new nodo<T>;
        nodo->dato=dato;
        nuovo->next=testa;
        testa=nuovo;
    };
    //Nodo è una classe che ha T dato e nodo* next
    Quando gli passo come T un tipo 'standard' tutto va bene, ma io vorrei capire meglio dal punto di vista teorico che succedde se gli passo un vettore, una stringa, una struttura o un oggetto cioè cosa ci sara in nodo->dato, un puntatore o l'intera oggetto/struttura...?

  3. #3
    l'intero oggetto/struttura (supponendo che nodo->dato sia di tipo T).
    Osserva che naturalmente il compilatore non ti compila finché il tipo complesso T non ha tutti gli operatori che tu usi per nodo->dato.

  4. #4
    Osserva che naturalmente il compilatore non ti compila finché il tipo complesso T non ha tutti gli operatori che tu usi per nodo->dato.
    Cioè, correggimi se ho capito male, devo ridefinire tutti gli operatori per l'oggetto T come quelli aritmetici, logici, d'incremento e condizionali?
    Ma è comunque un lavoro assestante dalla mia classe nodo, giusto?

  5. #5
    Originariamente inviato da dunix87
    Cioè, correggimi se ho capito male, devo ridefinire tutti gli operatori per l'oggetto T come quelli aritmetici, logici, d'incremento e condizionali?
    Ma è comunque un lavoro assestante dalla mia classe nodo, giusto?
    Solo gli operatori e metodi che utilizzi per il tuo modello nodo.

    Ad esempio se nella tua classe modello effettui sqrt (nodo), allora devi definire la funzione sqrt che si prenda in argomento il tuo nodo di tipo tua classe, oppure un'operatore di casting dalla tua classe ad un tipo digeribile da sqrt. Altro esempio se nella tua classe modello, "nodo" non viene mai sommato ad un intero, allora non è necessario che la tua classe sia sommabile ad un intero. ecc..

    Insomma se scrivi "nodo + 1" il compilatore deve sapere come farlo. E questo glielo puoi dire solo tu.
    ;-)

  6. #6
    Ah si ora ho capito...

    Quindi se io uso la mia classe nodo all'interno sempre della stessa classe stack(esempio postato sopra), nella quale definisco un metodo di ricerca o di ordinamento(anche se non ha senso in una pila, ma mi serve solo da esmpio), devo ridefinire gli operatori di confrono <, >, == e !=, se passo un tipo oggetto allo stack, giusto?

    Ma questa ridefinizione va fatta nella classe dell'oggetto che uso come tipo?
    Non posso farla a priori nel mio template stack? e soprattutto se non li ridefinisco che succede potrebbe compilarlo ugualmente?

    Grazie dei chiarimenti che mi stai fornendo

  7. #7
    Ho provato a ridefinire due operatori == e != per la classe che uso come tipo all'interno del mio stack per provare la funzione find. Ho provato a fare uno stack di stack.

    Però il compilatore (dev c++) mi restituisce un errore di questo tipo:
    no match for 'operator!=' in 'dato!=d'
    candidates are 'bool stack<T>:perator==(stack<T>&)[with T=stack<int>]'


    dato e d sono entrambi di tipo T (in questo caso sarebbero stack<int>).

    Come posso risolvere questo errore, io proprio non capisco perchè non funzioni

  8. #8
    E' lo scotto da pagare nell'uso dei template: messaggi un po' forvianti negli errori di compilazione. Ma dopo un po' ci si abitua. Come li definisci gli operatori == e != ? Come vengono usati nella classe template?
    insomma posta il codice.

  9. #9
    Infatti ho notato che si creano un po' di problemi.
    Allora ti posto le definizioni degli operatori all'interno di stack:
    codice:
    template<typename T>
    bool stack<T>::operator==(stack<T> &nuovo)
    {return this == &nuovo;}
    
    template<typename T>
    bool stack<T>::operator!=(stack<T> &nuovo)
    {return this != &nuovo;}
    Mentre il codice del metodo find è il seguente:
    codice:
    template <class T>
    iterator<T> stack<T>::find(T const &d){
        iterator<T> iter; 
        iter.pos=this->top;
        T dato=((iter.pos)->getData());//get data è un metodo che semplicemente ritorna T dat 
        while((dato!=d) && ((iter.pos)!=this->tail)) {
            ++iter;
            dato=((iter.pos)->getData());//
        }
        if(dato==d) return iter;
        else{ 
            iter.pos=NULL;
            return iter;
        }
    };
    Spero di aver messo tutto

  10. #10
    Originariamente inviato da dunix87
    Spero di aver messo tutto
    Non basta: così si devono indovinare troppe cose. Posta qualcosa che secondo te dovrebbe essere compilabile, ma non lo è, e tutta la pappardella degli errori che ti genera.

    intanto (se vuoi fare le cose fatte bene) metti a const gli argomenti ed i metodi che non ti servono non essere const:
    ad esempio:

    Codice PHP:
    // MacApp: argomenti e metodi const
    template<typename T>
    bool stack<T>::operator==(const stack<T> &nuovo) const
    {return 
    this == &nuovo;}

    template<typename T>
    bool stack<T>::operator!=(const stack<T> &nuovo) const
    {return 
    this != &nuovo;} 

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 © 2025 vBulletin Solutions, Inc. All rights reserved.