[C++] Consiglio

Vsc1
Salve a tutti, dovrei fare una rubrica... ho una classe base Contatto da cui derivano Privato e Lavoro, ora la rubrica dovrebbe avere max 500 contatti, per sfruttare i metodi virtual delle classi derivate utilizzo dei puntatori a Contatto. Ho fatto nella classe Rubrica un vector di puntatori a Contatto e un ulteriore metodo per verificare che non si superi la dimensione max(in realtà avevo provato a farlo di dimensione 500 ma il compilatore mi dava errore... forse perchè non era static) il mio problema è che non riesco a gestire bene questa rubrica, in pratica ogni metodo( aggiunta, modifica ecc.) dovrebbe tornare un puntatore all'oggetto corrente. Forse mi conviene farlo con un array dinamico? perchè se per esempio devo stampare l'oggetto corrente mi devo scorrere sempre il vector, avrei bisogno di qualche suggerimento :( Grazie

Risposte
apatriarca
In base alla mia esperienza, quello che hai descritto è un pessimo uso di ereditarietà. Che cosa differenzia davvero Privato e Lavoro? Molto poco suppongo. E come pensi di gestire una persona per cui sia disponibile sia un contatto privato sia uno lavorativo? Per non parlare di situazioni più complicate come persone che hanno parecchi contatti diversi dello stesso tipo. Ma suppongo che tutto ciò sia in parte stato scelto dal tuo professore.

Non mi è chiaro il motivo per cui un array di dimensione fissata non abbia funzionato, ma non ha molta importanza (con vector dovrebbe comunque essere più semplice). Qual'è invece il problema nel restituire il contatto che hai appena aggiunto/modificato? Non capisco in cosa incontri difficoltà dalla tua descrizione, prova a inserire il tuo codice in modo da poterne discutere meglio.

Vsc1
In effetti è l'esercizio che è impostato in questa maniera... il caso in cui il contatto sia di entrambe le tipologie non è considerato e la differenza sta in due attributi per entrambi le classi. Metto alcuni pezzi del codice per capire meglio il mio dubbio.
Questo è il metodo per verifica che non si superi la dimensione massima(rub è il mio vector della classe rubrica):
Contatto* Rubrica::dimMax(){
	if(rub.size()>500){
		rub.pop_back();
		cout << "Rubrica piena! Salvataggio fallito" << endl;
	}

	return *(rub.end()-1);
}

la mia intezione era quella di fare ritornare un puntatore all'ultimo oggetto del vettore, per cui poi per esempio aggiungi contatto privato la faccio così:
Contatto* Rubrica::addP(){
	Contatto* nuovo=new Privato();
	rub.push_back(nuovo);
	return dimMax();
}

Un esempio di utilizzo... istanzio il mio oggetto della classe Rubrica che contiene un vettore di puntatori a Contatto e tutti i metodi richiesti, poi dichiaro un puntatore a contatto a cui assegno sempre l'oggetto Contatto corrente. Ora il mio dubbio è che in questa maniera più che un puntatore all'elemento dell'array ho un puntatore all'oggetto stesso. In pratica in rubrica dovrei avere due metodi con cui posso cambiare il contatto corrente... se per esempio ho una rubrica di due contatti il contatto corrente è il secondo ma voglio stampare il primo, con il metodo indietro posso spostare il puntatore al contatto precedente per stamparlo
Spero di essere stato chiaro nell'esposizione del mio dubbio :?

apatriarca
Io non credo abbia senso restituire l'ultimo valore inserito quando la dimensione massima della rubrica è stata raggiunta. Dal punto di vista dell'utente non hai infatti alcun modo per sapere se il valore restituito è un contatto nuovo o un contatto già esistente che quindi vai a sovrascrivere. Sarebbe a quel punto meglio restituire 0 (o NULL o nullptr). Questo controllo ha poi secondo me senso farlo prima di inserirlo nel vettore (se avessi un array invece che std::vector saresti in effetti costretto a farlo prima). Per cui secondo me dovresti semplicemente avere
Contatto *Rubrica::addP() {
    if (rub.size() >= 500) { return 0; }

    Contatto *nuovo = new Privato;
    rub.push_back(nuovo);
    return nuovo;
}

Credo di aver compreso il tuo dubbio, ma non sono sicuro che cosa risponderti. Avrei bisogno di avere una visione più vasta del tuo problema e non solo questo metodo. Sarebbe anche utile sapere quale sia esattamente la richiesta del professore in modo da non andare contro quelle che sono richieste esplicite dell'esercizio.

Vsc1
in pratica i metodi della Rubrica (modifica, cancella, stampa) non mi devono permettere di scegliere a quale contatto voglio applicarli ma si devono applicare sempre al contatto corrente (quindi credo l'ultimo aggiunto) se poi vorrei applicarli a qualche altro contatto dovrei fare due metodi per andare avanti ed indietro, ecco perchè penso che mi serva che le funzioni ritornino un puntatore all'elemento del vector... quindi anche quando la dimensione è massima dovrei puntare ad un elemento.
Ho modificato il mio codice in questa maniera:
vector<Contatto*>::iterator Rubrica::dimMax(){
	if(rub.size()>500){
		rub.pop_back();
		cout << "Rubrica piena! Salvataggio fallito" << endl;
	}

	return (rub.end()-1);
}

vector<Contatto*>::iterator Rubrica::addP(){
	Contatto* nuovo=new Privato();
	rub.push_back(nuovo);
	delete nuovo;
	return dimMax();
}

Ha senso fare così se nel mai istanzio un oggetto Rubrica e un iteratore ad un vector?

apatriarca
Io credo che il professore stesse pensando a qualcosa di diverso. Credo tu debba semplicemente salvarti l'indice del contatto corrente da qualche parte dentro alla classe e le funzioni per modificare, cancellare o stampare il contatto corrente devono fare uso di questo indice (o iteratore o altro). A quel punto hai che andare avanti e indietro significa semplicemente incrementare o decrementare questo contatto corrente (verificando di non superare i limiti).

Continuo a pensare inoltre che nel caso di fallimento nell'inserire un contatto debba essere restituito un errore.

Vsc1
Alla fine mi hanno inviato una possibile soluzione del prof, nella quale aveva pensato la classe Rubrica con un array di puntatori a Contatto e un intero che si riferiva all'indice del contatto corrente... Per come l'avevo pensata io (con il vector e l'iteratore) andava tutto bene fino a quando non dovevo accedere ad un metodo virtual, ci sarà la soluzione ma non ci sono arrivato. Grazie dell'aiuto

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.