Newsgroup: it.comp.lang.c++
Titolo: [lamer] problema di design

Salve,
sono un niubbo dei linguaggi OO (sto leggendo a tempo perso la guida -che
trovo ottima, specie perché altre non ne ho...- di Bruce Eckel), e vorrei
sapere (prima di mettermi a studiare seriamente il C++, che altrimenti non
mi serve perché mi trovo piuttosto bene col C liscio) se è possibile fare
quanto segue.
Io avrei bisogno di creare degli oggetti (non so, mettiamo autoveicoli,
tanto per fare un esempio) che si comportino in maniera diversa, ognuno dei
quali è definito da uno o più "pacchetti d'azioni".
Faccio un esempio: un camion può muoversi (quindi avrà nella sua struttura
dati tutto il necessario per regolare e permettere il movimento, quindi
probabilmente un metodo move() e un array di ruote - lo so che è una cosa
cretina, è solo un esempio), può portare un carico (quindi avrà una
struttura che indica quale tipo di carico porta, e dei metodi carica(),
scarica(), etc.), può suonare il clacson (quindi avrà un metodo suona() ),
etc.
Un'auto può sempre muoversi (condividerà col camion lo stesso "pacchetto"
per muoversi), però non può portare un carico come lo può portare un camion
(avrà di conseguenza un pacchetto di dati+metodi per portare persone), e
così via.
Io conosco a tempo di compilazione tutti i "pacchetti", ed avrei bisogno di
assemblarli in combinazioni che conosco solo a runtime (per ottenere ibridi
tipo un oggetto che si può muovere come il camion ma che porta persone come
l'auto, per spiegarsi), ed eventualmente di aggiungere, modificare o
togliere ad un oggetto già creato un "pacchetto" (es. togliere all'auto la
possibilità di muoversi).
Ora, tutto ciò in un linguaggio procedurale lo saprei fare, ma la soluzione
non mi pare molto elegante, e vorrei sapere se è possibile implementare
qualcosa del genere in C++ in maniera elegante, un'idea che probabilmente
non funziona ma che mi viene sarebbe quella di creare una classe per ogni
pacchetto e poi creare tante sottoclassi che inheritino (<-- come si dice in
italiano?) da queste, così da ritrovarmi le strutture dati ed i metodi belli
assemblati, però in questo modo dovrei sapere già a compile time di quali
combinazioni di pacchetti ho bisogno.
Mi scuso per la scarsa precisione della richiesta e l'inadeguatezza del
linguaggio, nonché per il fare una domanda senza prima avere studiato il
C++ - magari esiste una soluzione banale ma non la conosco, e ringrazio
sentitamente chiunque mi risponderà.
Lanugo

 combinazioni di pacchetti ho bisogno.
Si dice ereditino.
Il punto è: come fai a sapere se un camion puo' portare dei carichi? Come
fai a sapere se la macchina si muove o no? Solitamente lo fai in base alla
classe dell'oggetto che ti appresti ad utilizzare (è un camion, i camion portano
carichi), come fai, se aggiungi a una macchina la possibilità di portare
carichi,
a far sapere che adesso può portare dei carichi?
E' chiaro, si può fare tutto, ma non è una cosa che ti mette a disposizione
il linguaggio. La cosa che mi viene in mente che assomiglia di più a quello che
vuoi fare sono gli oggetti COM.
PS
Il lamer che metti nel soggetto è una specie di autopunizione che ti infiggi
per qualche grave crimine che hai commesso in una vita precedente?

per qualche grave crimine che hai commesso in una vita precedente?
No, è perché non mi sembra carino irrompere in un NG chiedendo se in un
linguaggio che non conosco si può fare quello che voglio, perché giustamente
mi si potrebbe dire "leggiti i manuali".
Grazie per la risposta!
Lanugo

 etc.
Ovviamente una classe è un *tipo* e in C++ non si può cambiare a run-time.
Quello che ti serve può essere fatto, ma il punto è se ti serve davvero. Tu
ci hai chiesto "come implementare una certa soluzione" ad un problema che
non ci hai descritto. Probabilmente stai incorrendo in un problema di
design, ma se non ci spieghi il reale problema non possiamo aiutarti
davvero.
Comunque, supponendo che il tuo modello sia quello corretto, si può
realizzare quello che tu proponi. Un oggetto è infatti di un tipo ben
preciso ma ha un comportamento che può essere definito a run-time.
Nel caso specifico è possibile creare una classe base "veicolo" da cui
derivano "camion" e "auto". Inoltre si crea una classe astratta "operazione"
(bleah!) con un metodo virtuale puro operator()  e che esporta una stringa,
da cui derivare i metodi che ti servono (ridefinendo l'operator() ); la
stringa sarà il nome del tuo metodo.
L'idea è che "veicolo" ha una lista (direi una map, a prima vista) di classi
"operazione". "veicolo" avrà poi un operator(string methodName) che va a
cercare nella lista di metodi quello che si chiama "methodName" e ne chiama
l'operator() .
Ovviamente i metodi dovranno essere friend di veicolo e delle classi
derivate, perchè suppongo che i metodi dovranno poter accedere ai data
member delle tue classi!
Questa soluzione, comunque, porta più problemi di quanti ne risolva:
insomma, tu dici di sapere solo a run-time quali metodi avrà una classe, ma
quando devi chiamare un metodo, devi avere l'informazione che quel metodo è
effettivamente presente. Rischi di chiamare un metodo che non esiste.
Pazienza, dirai, lanciamo un eccezione! Ma io non credo che un eccezione sia
la soluzione. Dopo quell'eccezione, infatti, non ti rimane che terminare il
programma! Una classe che funziona in questo modo non sarà mai riusabile.
Inoltre per chiamare un metodo devi avere delle informazioni aggiuntive (che
ti dicono se la classe ha quel metodo!); bisognerebbe sempre evitare
"precondizioni sequenziali" per i metodi (del tipo: "prima di chiamare f1()
bisogna chiamare f2() e f3()" ) perchè sono una frequente causa di errori
(per la scarsa documentazione).
Concludendo: un oggetto ha un tipo preciso (la sua classe) e un tipo ha
associate alcune operazioni (i metodi della tua classe) che non sono
modificabili nel tempo. Pensala così: un numero reale ha sempre associate le
operazioni somma, moltiplicazione... e non "appaiono" e "scompaiono" mai.
Riconsidera il tuo problema originale, e vedrai che c'è una soluzione più
semplice (se cerchi di pensare alle classi come agli elementi del problema e
non della soluzione).
Se dai un'occhiata all'articolo "L'ereditarietà nei casi reali" di C. Pescio
(disponibile a partire dalla sua home page 
www.eptacom.net
 ) capirai qual'è
la soluzione corretta nei casi in cui ti sembra che un oggetto debba poter
"cambiare classe" a run-time.
Daniele.

runtime.
a questo punto io farei una cosa (molto brutta e passibile di
ottimizzazioni varie) del genere:
class Veicolo {
	public:
  	class bad_verb { };
  	enum Azioni { niente=0, muovere=1, suonare=2,
  		caricare=4, scaricare=8 }; // potenze di 2
    Veicolo(): attributi(niente) { }
    void CambiaAttributo(Azioni a) {
    	attributi = static_cast<Azioni>(attributi^a); }
    void muovi() {
    	if (!(attributi & muovere)) throw bad_verb();
      // codice normale
    };
    // e via via le altre azioni
	private:
  	Azioni attributi;
};
int main() {
	Veicolo a,b;
	a.CambiaAttributo(Veicolo::muovere);
	a.muovi(); // ok
	b.muovi(); // eccezione
}
Ciao Anto
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.44, higher than 97% of all previous test takers.
Visual Basic 5: 3.06, higher than 77% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688

runtime.
a questo punto io farei una cosa (molto brutta e passibile di
