Newsgroup: it.comp.lang.c++
Titolo: Queale possibile implementazione elegante del seguente problema?

Quale è, secondo voi, una possibile implementazione elegante del seguente
problema?
Si considerino due classi, rispettivamente Soggetto e Indirizzo, fra le
quali esiste un'associazione bidirezionale di tipo 0..1 <-> 0..n . Nel
mondo reale ciò potrebbe rappresentare l'associazione che esiste fra una
persona e gli indirizzi delle abitazioni correntemente di sua proprietà.
La classe Soggetto dovrà esportare solo due metodi pubblici,
aggiungiIndirizzo e rimuoviIndirizzo, che prendono come parametro un
puntatore a un oggetto di tipo Indirizzo ed eseguono le operazioni omonime
sulla lista di indirizzi gestita internamente.
La classe Indirizzo dovrà esportare un solo metodo pubblico impostaSoggetto,
che prende come parametro un puntatore a un oggetto di tipo Soggetto ed
associa l'indirizzo al più ad un soggetto (cioè, in particolare, se
l'argomento è null, l'indirizzo viene rimosso dal soggetto a cui
l'indirizzo stesso è eventualmente associato).
In definitiva, con questi tre metodi dovrà essere possibile:
1. aggiungere un indirizzo ad un soggetto:
   per esempio, s1->aggiungiIndirizzo(i);
2. rimuovere un indirizzo ad un soggetto:
   per esempio, s1->rimuoviIndirizzo(i);
3. assegnare un (altro) soggetto ad un indirizzo:
   per esempio, i->impostaSoggetto(s2)
4. rimuovere un eventuale soggetto ad un indirizzo:
   i->impostaSoggetto(null).
In virtù della cardinalità dell'associazione, si tenga ben presente che:
1. tramite Soggetto::aggiungiIndirizzo(), prima di aggiungere l'indirizzo al
nuovo soggetto, si dovrà prevedere in qualche modo anche la rimozione del
medesimo indirizzo dal soggetto che eventualmente tuttora lo detiene.
2. analogamente, tramite Indirizzo::impostaSoggetto(), prima di assegnare il
nuovo soggetto all'indirizzo, si dovrà prevedere anche la rimozione
dell'indirizzo dal soggetto che eventualmente tuttora lo detiene.
Grazie.


template < typename T > class OneToMany {
   std::vector< T* > m_Items;
   public:
   OneToMany () { };
   ~OneToMany () { };
   void add( T *item ) {
      m_Items.push_back(item);
   }
   void del( T *item) {
      m_Items.erase( find(m_Items.begin(), m_Items.end(), item) );
   }
};
class cIndirizzo {
   std::string address;
   public:
   cIndirizzo() { }
   ~cIndirizzo() { }
};
class cSoggetto {
   std::string nome;
   public:
   cSoggetto() { }
   ~cSoggetto() { }
};
typedef OneToMany<cSoggetto> Soggetto;
typedef OneToMany<cIndirizzo> Indirizzo;
Aloha,
Marco.

 typedef OneToMany<cIndirizzo> Indirizzo;
Forse volevi dire:
typedef OneToMany<cSoggetto> Indirizzo;
typedef OneToMany<cIndirizzo> Soggetto;
Ad ogni modo l'implementazione non rispetta le richieste:
- La cardinalità deve essere 0..1 <-> 0..n, cioè un soggetto può avere
0 o n indirizzi e un indirizzo al più un soggetto;
- La classe Indirizzo si trova ad avere in quel modo add() e del(),
che possono trarre in inganno l'utente: proprio perchè ogni indirizzo
può essere associato al più ad un soggetto, sarebbe piu' preciso
esportare un solo metodo impostaSoggetto().
- Entrambe le classi non sono "autosufficienti" con quella
implementazione:
aggiungere un indirizzo a due soggetti diversi implica la rimozione
dell'indirizzo dalla lista degli indirizzi del primo soggetto, prima
dell'aggiunta dell'indirizzo al secondo, affinchè venga rispettata la
cardinalità. Per lo stesso motivo, anche impostaSoggetto(): deve fare
in modo di rimuovere prima l'indirizzo dall'eventuale vecchio
soggetto.
Per cortesia, dato che esiste un altro thread identico a questo ma
piu' recente, che ho spedito per sbaglio al newsgroup, ti chiederei di
portare la discussione lì.
Grazie