Newsgroup: it.comp.lang.c++
Titolo: Lista di oggetti utilizzando ereditarietà e polimorfismo

Ciao amici. Sto studiando il C++ da circa un anno e proprio in questi
giorni penso di avere avuto una illuminazione (forse per voi puň
sembrare banale). Penso infatti di aver capito le funzioni virtuali
!!!
Vi prego correggetemi se sbaglio. Da quanto ho capito io potrei
costruire una classe generica (anche astratta) chiamata Oggetto.
Poi qualsiasi altra classe che creo la faccio derivata dalla classe
Oggetto.
Se io creo una classe Lista ed una classe ElementoLista cosě
strutturata:
class ElementoLista
{
  ....
  private:
	Object *Oggetto;
	ElementoLista *Next;
}
con l'utilizzo di opportune funzioni virtuali (ci devo ancora pensare
un po' perň) potrei evitare ad esempio di utilizzare la classe Liěst
della STL oppure utilizzare i templates. Ho sbagliato qualcosa? E'
possibile? Avete qualche consiglio?
Secondo voi, se fosse possibile questo, a rigor di logica dovrei
ottennere un codice oggetto piů leggero a scapito di un maggior
"carico di lavoro" run-time (che penso ininfluente).
Penso che per ora basti cosě ...
Vi prego aiutatemi e fate sě che la mia illuminazione (che se cosě
fosse potrei paragonare al giorno in cui ebbi la consapevolezza di
aver compreso i puntatori in C) non si spenga ...
Ciao
Gabriele

aver compreso i puntatori in C) non si spenga ...
:) :)
Ciao,
Angelo.

possibile? Avete qualche consiglio?
Con i templates puoi creare ad esempio una "lista di interi" o una "lista di
double" conservando il controllo dei tipi quando vai ad utilizzare un
elemento della lista.
Con la tua implementazione, invece, tutto diventa un Object.
Nel caso in cui la lista debba contenere elementi eterogenei non vedo
differenza se non nel fatto che il template e' gia' pronto.
Antonio Donatiello

lavoro a "run-time" (sempre relativo, considerata la potenza attuale dei
PC)
E` molto, MOLTO difficile battere una buona implementazione delle
librerie standard del C++.  Si veda, ad esempio,
 
http://www.sgi.com/Technology/STL/Slist.html
per una implementazione gratuita di buona qualita` del template
slist.  Usare, specificamente, slist<Object*> non dovrebbe poter
presentare alcuno svantaggio rispetto alla costruzione proposta,
mentre offre vari piccoli vantaggi.  Naturalmente, un vantaggio
intrinseco delle librerie standard e` che, man mano che "maturano",
soprattutto in un mercato competitivo, le menti migliori ci si
scervellano sopra a offrire le implementazioni piu` ottimizzate
e spinte.  E` d'altronde perfettamente lecito per un compilatore
riconoscere l'uso di template standard e usare per essi un qualche
generatore diretto di codice macchina ben al di la` delle normali
capacita` di ottimizzazione del compilatore stesso; oggi questo non
viene ancora fatto per le librerie standard C++, ma e` gia` molto
comune per tante funzioni delle piu` vecchie librerie standard C, al
punto che, pur essendo esse, a differenza di quelle C++, spesso mal
progettate [una funzione di concatenazione stringhe che rende la
costruzione di una stringa da varie altre una operazione O(N quadro),
e` veramente impossibile fare peggio di cosi`...!!!], nondimeno, da
un punto di vista del codice binario risultante, grazie agli "acceleratori
segreti" (e perfettamente leciti) impiegati dai migliori compilatori,
puo` oggi essere difficile batterle!
Ma torniamo a slist<Object *>.  La classe base del "nodo",
_Slist_node_base nella implementazione SGI sopra citata, si cura di
tutte le varie manipolazioni dei puntatori stessi della lista, in modo da
garantire, anche con compilatori-ciofeca, di poter evitare duplicazioni
inutili di codice (con compilatori decenti, come MSVC++6, le
duplicazioni dovute a template piu` semplici sarebbero comunque
rimosse da compilatore e linker, ma e` certo anche meglio non produrle
neppure).  Il template vero e proprio eredita pubblicamente da
questo, e non vi aggiunge altro che lo specifico campo-dati; neppure
una riga di codice, quindi nulla che possa appesantire.
Naturalmente, per usare le costruzioni Standard C++ e` meglio
disporre di un compilatore almeno minimamente vicino allo
standard stesso; uno che non implementi i template, ovvero che
li implementi in violazione dello Standard (per esempio, uno che
istanzi anche i template mai usati), produrrebbe risultati pessimi
per std::slist<Object*>...!
Per completezza, notiamo...:
Sia le liste proposte, sia quelle della libreria standard, sono
non-invasive.  Nel caso, non raro, in cui ogni oggetto debba
essere su di una "lista primaria", c'e` molto da dire anche a
favore delle liste *invasive*, ottenibili incorporando il campo
"puntatore al prossimo" nella stessa Object.  Questo dimezza
l'overhead di spazio della lista (1 puntatore per oggetto,
invece di due) e puo` migliorare le prestazioni.  Naturalmente,
le liste non-invasive offrono piu` flessibilita` (possibilita` di
porre un oggetto in un numero variabile di liste, di porlo in
una stessa lista piu` volte, ecc).
Un altro approccio, alternativo alle liste invasive, per migliorare
l'efficienza di tempo e di spazio, e` quello di tenere il dato
nel nodo per valore invece che con l'indirettezza del puntatore.
Questo, pero`, mal si attaglia a liste non omogenee, e, in
particolare, non utilizza il polimorfismo (puo` usare la
eredita` per implementazione, come nel caso gia` illustrato
della lista nella versione SGI della libreria standard C++).
Alex
Alex

e spinte.
Come gia' detto nella risposta al quesito di partenza non intendo discutere
sulla necessita' o meno di utilizzare le librerie standard. Mi permetto di
fare solo alcune considerazioni.
a) E' abbastanza facile migliorare la classe di una libreria standard se non
altro per il fatto che ci si puo' concentrare esclusivamente su quello che
serve in un dato periodo, evitando "costose" generalizzazioni.
b) Credo sia importante che nello studio del C++ i meccanismi piu'
importanti vengono compresi a fondo anche riscrivendo delle classi gia'
disponibili.
c) Ritengo che sia anche grazie a queste cose - escluso il mio modesto
contributo - che si possano avere delle persone in grado di migliorare
quanto gia' fatto, comprese le librerie standard.
Alla prossima,
Angelo.

quanto gia' fatto, comprese le librerie standard.
ANCHE grazie a "queste cose", certo -- ma non SOLO; incoraggiare
un principiante, che e` appena giunto ad una comprensione interiore
di un aspetto del polimorfismo, a riscriversi slist<>, non mi sembra
didatticamente ottimale nei suoi confronti.  Perche` non incoraggiarlo,
invece, ad approfondire l'esplorazione di questi aspetti (eredita` e
polimorfismo), nell'ambito dell'USO di slist<> (o altri appropriati template
standard), invece di mischiarli con i vari problemi di gestioni a basso
livello di inserimento-in-lista, rimozione-da-lista, eccetera, che slist<>
gia` offre, e con l'eredita` e il relativo polimorfismo non c'entrano?  Mi
pare didatticamente ed euristicamente piu` appropriato.
Rispetto le tue idee sulla didattica, anche se ne differisco con veemenza.
Alla fin fine, ogni principiante-autodidatta, o ciascun istruttore, seguira`
poi comunque il percorso didattico che piu` gli aggrada.
L'importante, comunque, e` mantenere queste attivita` di prototipazione,
studio, sperimentazione, eccetera, separate da quelle "di produzioni" --
per le quali, cadere nel "vicolo cieco" di modificare o reimplementare
parti delle librerie standard C++, e altri componenti riusabili, sarebbe
gravissimo, veramente da Kevorkian...!
Alex

Scusami ma ho perso un po' il "thread" del discorso...
In breve, a me non sembra di aver consigliato di modificare un componente
standard, ma soltanto di approfondire le proprie conoscenze sul linguaggio,
anche reinventando l'acqua calda se necessario.
Per il resto, con tutto il rispetto per la tua opinione, credo che la
pensiamo in modo differente su come insegnare e/o imparare.
Grazie per l'interessante dibattito,
Angelo Donatiello.

Grazie per l'interessante dibattito,
Il ringraziamento e` reciproco!
Alex