Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2011
    Messaggi
    15

    [C++] applicare una classe nella template class

    Ciao a tutti,
    ho un dubbio su come affrontare un'esercizio, è da un po' che ci provo, ma niente da fare. Forse ho interpretato male il professore... non so'.
    Nella prima parte chiedeva di creare una rubrica utilizzando una template class con le funzioni di add, remove e print. Fin qua funziona tutto bene.

    L'esercizio successivo, dice di implementare una classe Persona e applicarla con la template class appena creata (che ho chiamato ListaConcatenata.h).
    Quindi ho creato un nuovo file .cpp e .h che si chiama persona, poi ho cercato di usarla nel file ListaConcatenata.h, ma mi da errore.

    Metto anche una parte del codice del file ListaConcatenata.h:
    codice:
    #include <iostream>
    #include <stdlib.h>
    #include "persona.h"    //QUESTA è LA PARTE CHE HO AGGIUNTO
    using namespace std;
    
    template <class T>
    class LinkedList
    {
    private:
        string nome;
        string cognome;
        string telefono;
    
        Persona persona;   //QUESTA è LA PARTE CHE HO AGGIUNTO
    
       struct ListNode
        {
          T val1;
          T val2;
          T val3;
          ListNode * next;
          ListNode(T value1, T value2, T value3, ListNode * next1 = NULL)
          {
             val1 = value1;
             val2 = value2;
             val3 = value3;
             next = next1;
          }
        };
    
    
    public:
       LinkedList() { head = NULL;  }   
       ~LinkedList();      
                  
       void aggiungi();
       void elimina();
       void stampa();
    };
    e questa è la mia classe persona.h:

    codice:
    class Persona
    {
        public:
            char nome[30];
            char cognome[30];
            char tel[30];
    
    
            void add_nome( );
            void add_cognome( );
            void add_telefono( );
    };

    l'errore è
    ||=== Build: Debug in Rubrica (compiler: GNU GCC Compiler) ===|
    include\persona.h|1|error: redefinition of 'class Persona'|
    include\persona.h|1|error: previous definition of 'class Persona'|
    ||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

    Cosa sto sbagliando? è sbagliato l'approccio?
    Grazie.

  2. #2
    Probabilmente hai incluso il file Persona.h in più headers, con il risultato che nel .cpp finale di fatto la classe persona viene definita più volte. La soluzione standard per evitare le inclusioni multiple di un header è di usare i cosiddetti header guard: ogni .h dovrebbe avere il formato:
    codice:
    #ifndef NOME_FILE_H_INCLUDED // dove "NOME_FILE_H" è il nome del file .h in questione
    #define NOME_FILE_H_INCLUDED
    
    // qui il codice vero e proprio
    
    #endif
    Questo fa in modo che, se per un motivo o per l'altro il .h viene incluso più volte, solo nel primo caso viene effettivamente considerato il codice che contiene, evitando così errori di definizioni duplicate.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Nov 2011
    Messaggi
    15
    cavoli, era proprio quello il problema. Infatti non capivo quando serviva #ifndef e #endif in una classe.. ora è tutto chiaro.
    Grazie mille

  4. #4
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Nov 2011
    Messaggi
    15
    scusami, ma ho ancora un'altro dubbio, magari potresti illuminarmi!?! Consegnando l'esercizio, il professore mi ha risposto che lui si aspettava una cosa diversa nel main. Ti posto parte del codice del main:
    codice:
    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include "persona.h"
    #include "ListaConcatenata.h"
    
    using namespace std;
    
    int main()
    {
       ListaConcatenata<string> list;
       ....
    }
    Poi ad un certo punto nel main richiamavo la list.aggiungi() che è così implementata nella template class:
    codice:
    //********************************************************
    // Funzione che aggiunge un nuovo contatto nella rubrica *
    //********************************************************
    template <class T>
    void LinkedList<T>::aggiungi()
    {
        persona.add_nome();
        nome=persona.nome;
    
    
        persona.add_cognome();
        cognome=persona.cognome;
    
    
        persona.add_tel();
        telefono=persona.numero;
    
    
    
    
       if (head == NULL)
          head = new Contatto(nome, cognome, telefono);
       else
       {
          Contatto * nodoCorrente = head;
          while (nodoCorrente->next != NULL)
             nodoCorrente = nodoCorrente->next;
     
          nodoCorrente->next = new Contatto(nome, cognome, telefono);
        }
    }
    Tutto funziona correttamente, ma il professore dice che nel main si aspettava ListaConcatenata<Persona> list; Ho provato a mettere nel main il codice richiesto dal prof, ma giustamente, ho una valanga di errori perchè prima c'era la string, ora la classe Persona.... non capisco come correggere il programma, non so da dove partire!

    Grazie mille.

  6. #6
    Leggendo il codice, mi sembra che tu abbia un po' di confusione sulle "responsabilità" della classe LinkedList... la classe LinkedList<T> è una classe generica (template), che deve occuparsi semplicemente di contenere oggetti di un generico tipo T; perché fa riferimento a Persona o a Contatto? L'unico tipo "esterno" a cui deve fare riferimento LinkedList è T, ovvero l'argomento template.

    In altre parole: il punto dell'usare i template in questo caso è scrivere un contenitore che possa funzionare con qualunque tipo, senza rimanere legati a Persona o Contatto o quello che vuoi. Poi nel main o dove vuoi scriverai LinkedList<Contatto>, e ci potrai inserire dentro oggetti di tipo Contatto, che costituiranno la tua rubrica.

    Poi: la classe LinkedList ha un'interfaccia che non ha senso. Come può essere che aggiungi ed elimina siano funzioni che non prendono alcun argomento? Da dove pescano l'elemento da aggiungere/eliminare? Un'interfaccia più sensata sarebbe del tipo:
    codice:
    void aggiungi(T elemento);
    void elimina(T elemento); // su questo ci sarebbe da discutere, comunque...
    Anche sulla classe Persona, non capisco perché hai i metodi add_nome e compagnia: o lasci i membri pubblici (e da fuori ci scrivi dentro quel che ti pare), oppure metti i membri privati e scrivi i metodi getter e setter (string get_nome()/void set_nome(string nome)). Dei metodi come add_nome (che peraltro non riceve alcun parametro? ) per una struttura contenente un numero fissato di record non hanno senso.

    Io fossi in te ripartirei da capo, riordinandomi un po' le idee su cosa deve fare ciascuna classe, e cercando di capire quale dovrebbe essere l'interfaccia che dovrebbero esporre; se vuoi una mano in questo senso potrebbe essere utile avere la consegna completa del problema, visto che ci sono diverse cose che non mi tornano già così (come ci si aspetta che la print() faccia qualcosa di sensato su un tipo generico? come si dovrebbe scorrere una linked list con un'interfaccia di questo genere?).
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    Nov 2011
    Messaggi
    15
    Ciao MItaly,
    Quote Originariamente inviata da MItaly Visualizza il messaggio
    In altre parole: il punto dell'usare i template in questo caso è scrivere un contenitore che possa funzionare con qualunque tipo, senza rimanere legati a Persona o Contatto o quello che vuoi. Poi nel main o dove vuoi scriverai LinkedList<Contatto>, e ci potrai inserire dentro oggetti di tipo Contatto, che costituiranno la tua rubrica.
    ok, credo di aver capito l'errore concettuale che ho fatto...

    Quote Originariamente inviata da MItaly Visualizza il messaggio
    Poi: la classe LinkedList ha un'interfaccia che non ha senso. Come può essere che aggiungi ed elimina siano funzioni che non prendono alcun argomento? Da dove pescano l'elemento da aggiungere/eliminare? Un'interfaccia più sensata sarebbe del tipo:
    codice:
    void aggiungi(T elemento);
    void elimina(T elemento); // su questo ci sarebbe da discutere, comunque...
    Anche sulla classe Persona, non capisco perché hai i metodi add_nome e compagnia: o lasci i membri pubblici (e da fuori ci scrivi dentro quel che ti pare), oppure metti i membri privati e scrivi i metodi getter e setter (string get_nome()/void set_nome(string nome)). Dei metodi come add_nome (che peraltro non riceve alcun parametro? ) per una struttura contenente un numero fissato di record non hanno senso.
    non passavo alcun parametro perchè poi all'interno della funzione scrivevo delle cout e cin che mi chiedevano i valori, però collegandomi a quanto dicevi prima, non è corretto fare così perchè il template non sarebbe più generico, giusto!?

    Credo che mi sono confusa le idee nel momento in cui mi è stato detto di creare una nuova classe Contatto da utilizzare nel template ListaContatto, non so più chi deve fare cosa. O meglio, immagino che le operazioni di aggiunta rimozione e stampa debba essere fatta dal template, ma a questo punto a cosa mi serve la classe Contatto!?

    Scusa se sono un po' recidiva!!! ci sto provando...

  8. #8
    Quote Originariamente inviata da monia82 Visualizza il messaggio
    Ciao MItaly,
    non passavo alcun parametro perchè poi all'interno della funzione scrivevo delle cout e cin che mi chiedevano i valori, però collegandomi a quanto dicevi prima, non è corretto fare così perchè il template non sarebbe più generico, giusto!?
    Esatto. Concettualmente un container come LinkedList dovrebbe occuparsi esclusivamente di contenere gli elementi che gli viene detto di memorizzare "da fuori".
    Credo che mi sono confusa le idee nel momento in cui mi è stato detto di creare una nuova classe Contatto da utilizzare nel template ListaContatto, non so più chi deve fare cosa. O meglio, immagino che le operazioni di aggiunta rimozione e stampa debba essere fatta dal template, ma a questo punto a cosa mi serve la classe Contatto!?
    Non è molto chiaro neanche a me esattamente quello che ti è stato chiesto, per quello sarebbe utile che tu postassi il testo dell'esercizio. Una possibilità che mi viene in mente è che Contatto dovrebbe semplicemente contenere un oggetto Persona (che hai già, e che contiene nome e cognome) e ci aggiunge il numero di telefono. Ma, di nuovo, sarebbe meglio vedere il testo dell'esercizio, non vorrei indirizzarti in direzioni sbagliate.
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Utente di HTML.it
    Registrato dal
    Nov 2011
    Messaggi
    15
    Grazie MItaly,
    il testo è questo:
    realizzare una Template Class
    template<class T>
    class DblLinked
    {
    }
    implementare aggiungi(T& contatto), rimuovi(T& contatto)e la stampa dell'intera lista (operatore <<)
    Implementare una Classe Persona con dati uso rubrica telefonica e applicarla con la classe DblLinked

    A questo punto mi sta venendo il dubbio anche su come ho creato la struttura per la persona, io l'avevo fatta così:
    codice:
    class Persona
    {
        public:
            char nome[30];
            char cognome[30];
            char tel[30];
     
            void add_nome( );
            void add_cognome( );
            void add_telefono( );
    };

    ma il prof, tramite email, mi ha detto che si aspettava una "chiave" formata da nome e cognome, e il restante dei dati formati dalla coppia attributo-valore, in modo tale che quando stampo viene fuori:
    Mario Rossi
    cellulare - 123456
    cellulare2 - 987654
    indirizzo - blablabla...
    etc etc...


    quindi devo fare qualcosa di più dinamico, giusto? così come l'ho struttato non va bene, cosa mi consigli di fare?
    Grazie ancora per l'aiuto.

    ps. sto andando off topic? devo creare una nuova discussione?

  10. #10
    Quote Originariamente inviata da monia82 Visualizza il messaggio
    Grazie MItaly,
    il testo è questo:
    realizzare una Template Class
    template<class T>
    class DblLinked
    {
    }
    implementare aggiungi(T& contatto), rimuovi(T& contatto)e la stampa dell'intera lista (operatore <<)
    Implementare una Classe Persona con dati uso rubrica telefonica e applicarla con la classe DblLinked
    Ok, allora la cosa è piuttosto semplice.
    La classe DblLinked, come previsto, non deve entrare nel merito, ma semplicemente fornire uno storage generico per il tipo T; la aggiungi andrà ad aggiungere un nodo in coda (o in testa) alla lista, copiandoci dentro il valore che ti viene passato (nota che qui `contatto` non è inteso come tipo, ma semplicemente come nome del parametro della aggiungi).

    Analogamente, nella rimuovi andrai a cercare un nodo il cui elemento risulta uguale a quello che ti viene passato ed eliminerai il nodo corrispondente.

    Nella stampa poi userai l'operatore << per stampare tutti gli elementi (scorri la lista e per ciascun elemento fai std::cout<<nodo.elemento).

    [/I]A questo punto mi sta venendo il dubbio anche su come ho creato la struttura per la persona, io l'avevo fatta così:
    [/FONT]
    codice:
    class Persona
    {
        public:
            char nome[30];
            char cognome[30];
            char tel[30];
     
            void add_nome( );
            void add_cognome( );
            void add_telefono( );
    };
    [FONT=arial]
    ma il prof, tramite email, mi ha detto che si aspettava una "chiave" formata da nome e cognome, e il restante dei dati formati dalla coppia attributo-valore, in modo tale che quando stampo viene fuori:
    Mario Rossi
    cellulare - 123456
    cellulare2 - 987654
    indirizzo - blablabla...
    etc etc...
    Boh, per ora non starei a preoccuparmene, il testo del problema non mi sembra che menzioni nulla del genere, e una cosa del genere richiede un po' più di "magia" di quanto credo sappiate usare.

    Per il resto, per Persona io mi aspetterei una cosa del tipo:
    codice:
    struct Persona
    {
        std::string nome;
        std::string cognome;
        std::string indirizzo;
        std::string telefono1;
        std::string telefono2;
    };
    (ammesso che possiate usare std::string, in caso contrario dovranno essere degli array di char).

    Le altre due cose importanti da implementare a quel punto sono:
    • l'overload dell'operator== (altrimenti la lista non può sapere nella remove quando due elementi sono uguali);
    • l'overload dell'operator<< (altrimenti la lista non può stampare gli elementi nella stampa()).

    Le due cose ti risultano più o meno note?
    Amaro C++, il gusto pieno dell'undefined behavior.

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.