[C++] problema con ereditarietà multipla

di il
11 risposte

[C++] problema con ereditarietà multipla

Salve a tutti, sono nuovo e ho il seguente problema:
sto realizzando un programma in C++ utilizzando Visual C++ 6.0 e ho una situazione di questo tipo:


    class persona{
          string attributo1;
    ...
    }

    class padre : virtual public persona{
          string attributo2;
    ...
    }

    class madre : virtual public persona{
          string attributo3;
    ...
    }

    class figlio :public padre,public madre{
          string attributo4;
    ...
    }
ogni sottoclasse eredita l'attributo della classe dalla quale eredita... insomma mi trovo di fronte ad un classico caso di ereditarietà multipla...

il problema è che ho creato una rubrica in cui ho un array di puntatori a "persona" e un contatore che parte da 0 e viene incrementato ogni volta che viene aggiunto un indirizzo nell'arrey:
    int count=0;
    persona *persone[100]
e quando devo riempire questo array con sottoclassi della classe "persona" faccio così:

    
     persona[count] = new madre;
    (persone[count]->attributo1="tizia";
    ((madre *)persone[count])->attributo3="generosa";
    count++;
ma, nel far questo, il programma non parte poichè segnala il seguente errore riferito alla riga di codice che ho sottolineato:

- cannot convert a 'persona*' to a 'madre*'; conversion from a virtual base class is implied

Se invece faccio ereditare padre e madre da persona come classe base normale e NON come virtual ,questo problema si risolve ma , nel momento in cui voglio rempire l'arrey con puntatore a classe figlio in questo modo:

  
     persona[count] = new figlio;                                 /*1*/
    (persone[count]->string1="caio";
    ((figlio *)persone[count])->string2="permaloso";   /*2*/
    ((figlio *)persone[count])->string3="veloce";         /*3*/
    ((figlio *)persone[count])->string4="basso";          /*4*/ 
    count++;
ho uno errore riferito alle righe 1,2,3,4 e cioè:

- ambiguous conversions from 'class figlio *' to 'class persona *'

Allora ,rimuovendo sempre l'ereditarietà "virtual" come ho fatto prima ,ho risolto così:

  padre* p;
     p = new figlio;
     persona[count] = p;                                 
    (persone[count]->string1="caio";
    ((figlio *)(padre *)persone[count])->string2="permaloso";   
    ((figlio *)(padre *)persone[count])->string3="veloce";        
    ((figlio *)(padre *)persone[count])->string4="basso";          
     count++;

così funziona a meraviglia, ma francamente mi sembra molto strana come soluzione....e poi io vorrei dichiarare l'eredità di padre e madre da persona come virtual per evitare che nell'oggetto figlio ci siano 2 copie di persona..

Qualcuno di voi potrebbe darmi delucidazioni a riguardo?...per me è molto importante poichè devo presentare al mio professore un progetto che ha all'interno un meccanismo simile...

11 Risposte

  • Re: [C++] problema con ereditarietà multipla

    Il tuo problema è che crei delle classi persona e poi fai il cast a seconda del caso.
    Se invece crei la classe supponiamo filgio allora lui in automatico chiama le classi base durante la costruzione e quindi senza bisogno di cast.
    Io non vedo la neccesità di creare un array di 100 persone fatte in quel modo. Non so poi cosa ci devi fare con sto array.
    Dammi un esempio di utilizzo che troviamo il modo + efficacce x la multipla eredità.

    esempio:
    
    figlio* p;
         p = new figlio;                        
         p->string1="caio";
         p->string2="permaloso";   
         p->string3="veloce";       
         p->string4="basso";         
    
    siccome persona è la classe base di tutto tu non puoi fare il cast da figlio a persona in quanto vai a perdere le info che figlio eredita da padre e madre ovvero sono delle info a cui non puoi accede dalla classe base siccome il figlio è un evoluzione delle classi padre,madre le cui a loro volta sono delle evoluzioni dalla classe persona. (evoluzione significa estensione dalla classe base).
  • Re: [C++] problema con ereditarietà multipla

    Ho bisogno dell'array perchè sto costruendo una rubrica che deve contenere al suo interno oggetti di diverso tipo, ma che ereditano tutti dalla classe base "persona"...

    nel caso specifico del progetto che sto costruendo, ho una classe persona, tre sottoclassi che ereditano da persona (amico,parente e collega) e poi ho due sottoclassi paricolari : collega\amico che eredita da collega e da amico e poi collega\parente che eredita da collega e da parente...

    gli indirizzi di oggetti di tutte queste categorie devono stare insieme all'interno di un array di puntatori alla classe base...ecco perchè sono costretto ad utilizzare l'array di indirizzi...
  • Re: [C++] problema con ereditarietà multipla

    Allora mi sa che l'hai capito male l'eredita dalle classi. Tu crei dei superClassi e non dei sottoclassi. ti faccio l'esempio della rubrica così mi spiego meglio:
    
    classe base: umano
    
    class umano
    {
    public:
    	umano(){};
    	virtual void ~umano(){};
    	std::string nome;
    	std::string cognome;
    };
    
    classe persona che eredita da umano il nome ,cognome e altre cose base (sesso o che ne so)
    
    class persona public: umano
    {
    	std::vector<persona *> listaAmici;
    	std::vector<persona *> listaColleghi;
    };
    
    
    una persona quindi ha un nome e cognome ereditata dalla classe base umano ma ha una lista di amici e colleghi. La lista l'ho creata come un vettore di puntatori a oggetti uguali a lui (sempre persone sono) e come lui ereditano dalla classe base (umano) nome e cognome.
    Adesso per fare la rubrica tu basta che crei un vettore di Persone e non di umani che non sanno niente di amicizia o di colleghi quindi crei una lista di superclasse.
    
    std::vector<persona> rubrica;
    per aggiungere una persona alla rubrica fai:
    
    persona nuovaPersona;
    
    nuovaPersona.nome = "Pippo";
    nuovaPersona.cognome = "Cognome Pippo";
    rubrica.push_back(nuovaPersona);
    
    in ogni momento puoi estendere la lista di amici e colleghi di questa persona in questo modo:
    trova un elemento a cui aggiungere un amico supponiamo rubrica[0];
    trova un altro elemento a cui lui è amico supponiamo rubrica[1];
    per aggiungere un amico fai così:
    
    rubrica[0].listaAmici.push_back(&rubrica[1]);
    
    Non hai bisogno ne di allocare dinamicamente (la classe vector è + furba di noi umani) e neanche di fare delete alla fine siccome il RAII della classe vector lo fa automaticamente.
  • Re: [C++] problema con ereditarietà multipla

    Un altro metodo per essere + in linea a ciò che vuoi fare tu è:

    definire una classe persona che contiene tutte le opzioni che possono contenere le varie classe ereditiere e fare delle funzioni pure virtual nella classe persona così che ogni classe discendente può esporrere la sua versione della funzione.
    Esempio:
    
    class persona
    {
       persona();
       string nome;
       string cognome;
       vector<persona *> listaAmici;
       vector<persona *> listaColleghi;
       virtual string CosaSonoio() = 0;
       void InserisciNome(string _nome){nome = _nome;};
    }
    
    class Amico : public persona
    {
      Amico();
     virtual string CosaSonoIo(){return "Amico");
     InserisciNome(string nome){persona::InserisciNome(nome);};
    }
    
    class collega : public persona
    {
      collega();
     virtual string CosaSonoIo(){return "collega");
     InserisciNome(string nome){persona::InserisciNome(nome);};
    }
    
    
    ti crei poi il tuo array di persone così:
    
    persona *rubrica[100]; 
    rubrica[0] = new Amico;
    rubrica[1] = new collega;
    .....
    
    Vedi tu cosa ti piace di +.
  • Re: [C++] problema con ereditarietà multipla

    Grazie mille per l'aiuto che mi stai dando...se i molto gentile...

    Comunque per ciò che voglio fare preferisco la seconda opzione e sto seguendo quella...solo che non ho capito alcune cose:

    ho creato l'array di persone (come mi hai mostrato nell'ultima porzione di codice che hai postato) all'interno di una classe che si chiama "rubrica"(che non c'entra nulla con la classe persona e con le sue sottoclassi)....

    il problema è che nel mio progetto amico,collega e parente, oltre al nome,al cognome e al numero di telefono (gli attributi che ereditano da persona) , possiedono degli attributi prorpri della loro clesse...amico ha una stringa che si chiama "contesto di amicizia"....collega ne ha una che si chiama "ruolo lavorativo"....parente ne ha una che si chiama "grado parentela"...

    come faccio a settare questi attributi all'interno delle sottoclassi di persona presenti nell'array?

    cioè, dopo che ho instanziato un oggetto di tipo amico nella memoria heap o l'ho inserito nell'array in questo modo:
        
    persona *rubrica[100];
    rubrica[0] = new Amico;
    
    come faccio ad inserire "contesto di amicizia"?

    con il cast?
    
    (amico*)rubrica[0]->contesto_di_amicizia="calcetto";
    
  • Re: [C++] problema con ereditarietà multipla

    In questo caso si. Sarebbe meglio fare una cosa del genere almeno è + pulito.
    
    amico *temp = dynamic_cast<amico *>(rubrica[0]);
    temp->contesto_di_amicizia = "calcetto";
    
    Non credi che avrai difficoltà poi a raccogliere che ne so: tutti gli amici di una persona in rubrica?
  • Re: [C++] problema con ereditarietà multipla

    Ma tra le persone della rubrica non c'è nessun rapporto...ogni indirizzo dell'array si riferisce ad una persona (normale,amico,parente,collega,ecc) che non ha niente a che vedere con le altre...

    è una rubrica telefonica (tipo quella dei cellulari) e i rapporti di amicizia sono in relazione all'utente che utilizza la rubrica...

    mentre le persone normali avranno solo nome,cognome e numero di telefono, gli amici ,ad esempio, avranno oltre a questi anche un altro attributo (ad esempio contesto_di_amicizia="conosciuto a calcetto")...forse non mi sono spiegato bene nei post precedenti...
  • Re: [C++] problema con ereditarietà multipla

    Allora stai faccendo giusto. Io ero partito che ognuno di questi elementi aveva un legame con un altro sempre nella stessa lista. Per quello che ti ho proposto la prima soluzione che mi sembrava + appropriata.
  • Re: [C++] problema con ereditarietà multipla

    Mi sapresti dire perche il cast non funziona nel caso in cui padre e madre ereditino persona come virtual?
  • Re: [C++] problema con ereditarietà multipla

    Perche se tu dichiari public virtual allora il compilatore presupone che tu dovresti sviluppare dentro le classi discendenti anche il ctor e dtor (constructor,destructor) della classe base cosa che tu non fai. A parte che non ho mai visto un public virtual in tutte le classi in cui sono andato incontro. Mettendolo come virtual tu dici che il constructor della classe base sarà il constructor della classe discendente cosa che non è vera.
  • Re: [C++] problema con ereditarietà multipla

    Skynet,ti ringrazio di cuore per il tempo dedicatomi
Devi accedere o registrarti per scrivere nel forum
11 risposte