Newsgroup: it.comp.lang.c++
Titolo: Utilizzazione effettiva delle STL

Ciao ALL!
Volevo sapere se le STL sono uno standard usabile oppure sono uno
schifo. Non ho capito bene.
Come mai molti non le usano e preferiscono riscriversi da 0 classi
come la string, per esempio?
Dove trovo un manuale delle STL in rete?
In definitiva: mi consigliate di usarle o no?
Ciao_______________
http://siena.linux.it
 -  S L U G  homepage
Leva "civetta" dal mio indirizzo.
http://dinogen.tripod.com
 - la mia homepage

come la string, per esempio?
Ma sei fuori? 8)
Luc.

 In definitiva: mi consigliate di usarle o no?
Ti consiglio di impararle e di verificare quanto la tua implemntazione e'
"conforme". Poi deciderai tu.
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 In definitiva: mi consigliate di usarle o no?
Certamente si, anche in progetti commerciali, posto di usare un
compilatore che la supporti decentemente.
Ciao,
Nicola

da soli che non a usare quelle gia' esistenti e scritte *meglio*.
I due esempi di riscrittura che mi hanno incuriosito sono questi:
la classe qtstring delle qt.
la classe Cstring della MFC.
In più ho un paio di amici anti-stl.
Volevo sapere la vostra opinione


 In più ho un paio di amici anti-stl.
E cosa obbiettano?
Ciao,
Nicola

E cosa obbiettano?
Che sono inefficienti e che è meglio strcpy e compagnia.
Ma io ieri ho letto la documentazione che mi avete indicato.
Mi sembra una roba fantastica.


 Che sono inefficienti e che è meglio strcpy e compagnia.
Chiedi che ti presentino dei numeri. L'STL e' scritto in modo da essere
quasi completamente espanso inline. Con un compilatore decente
l'overhead in termini di tempo e' spesso minimo.
Senza contare che se hanno cosi' tanta voglia di fare i conticini con i
puntatori, che si divertano. Francamente la mia vita di programmatore e'
migliorata quando ho cominciato a usare '=' e '+' per comporre stringhe.
Ciao,
Nicola

 Che sono inefficienti e che è meglio strcpy e compagnia.
Chiedendo scusa a Davide per il furto, direzionali a
http://utenti.tripod.it/papero/news/cversusc.txt


In definitiva: mi consigliate di usarle o no?
Si. ma attento che non sono esattamente la cosa più facile di questo
mondo.
Il Ghenio
WINWORD.EXE - ERRORE DI APPLICAZIONE
l'istruzione a "0x3017ff27"ha fatto riferimento alla
memoria a "0x02a3143c".La memoria non poteva essere 'read'.

Volevo sapere la vostra opinione
A volte che e' contro la libreria standard (immagino che
tu intenda questo con "stl") e' semplicemente affetto dalla
sindrome "non l'ho scritto io" oppure "perche' le cose
divertenti le devono fare tutte gli altri ?".
Io non sono "anti-stl"... anche se devo ammettere di
soffrire di una forma grave di entrambe le sindromi citate.
Secondo me e' pero' giusto ammettere che si tratta di una
libreria relativamente "giovane" che soffre di problemi
di gioventu'. Inoltre ho personalmente incontrato
problemi di questo tipo:
  - Messaggi di errore al limite del comprensibile (per me)...
    ovviamente la comprensibilita' e' soggettiva; ma indicare
    con due schermate di "schifezze" il fatto che si sia
    dimenticato di scrivere un "const" non e' il massimo
    (in particolare per chi si avvicina al C++).
    Il problema non e' nelle librerie ma nella giovane
    tecnologia template... forse in futuro le cose
    miglioreranno.
  - Espansione inline esagerata: una istruzione del tipo
             m["Andrea"]="Griffini"
    viene compilata in 2Kb di codice da BCC55 (*ogni* singolo
    utilizzo di questo tipo di una istanza di 
    std::map<std::string,std::string> richiede questa
    quantita' di codice, oltre a questo vengono ovviamente
    fatte chiamate a funzioni di libreria - ad esempio per
    allocare memoria).
    Non so cosa venga fatto esattamente ma *forse* l'intera
    logica di inserimento nel rb-tree viene espansa inline (!).
    Per chi pensa che 2Kb per una istruzione siano ragionevoli
    posso dire di aver visto gente scrivere in 4Kb una
    simulazione del primo livello di Descent... un gioco 3D
    con texture-mapping prospettico a 6 gradi di liberta';
    la simulazione occupava 4Kb in tutto (dal calcolo delle
    texture all'engine di rendering al controllo di camera
    alle animazioni).
    Una soluzione che mi era stata proposta era quella di
    disabilitare *globalmente* l'espansione inline. Anche
    questo ha pero' qualche seria controindicazione dal punto
    di vista delle prestazioni.
  - Mancanza di supporto multithread (lo standard non parla
    di multithreading e quindi chi usa una libreria "standard"
    dovrebbe semaforizzare tutti gli accessi).
    Anche la sola *lettura* di strutture dati da parte di piu'
    thread contemporaneamente puo' portare a problemi seri con
    alcune implementazioni.
  - Problemi di condivisione di container STL fra programmi
    compilati separatamente. Con alcune implementazioni sotto
    Windows ad esempio passando una istanza std::map da un
    programma C++ ad una DLL scritta in C++ non si riesce ad
    accedere nemmeno in lettura.
    Sono anche prevedibili problemi in caso di modifica di
    container standard (ciascuno dei due programmi ha una
    propria gestione della memoria... se un std::vector
    creato da uno viene esteso dall'altro si possono ovviamente
    creare problemi molto seri).
    Con strutture dati piu' semplici (es. buffer di lunghezza
    fissa, stringhe "C") questi problemi sono meno subdoli.
    Le strutture dati "esplicite" si prestano bene inoltre per
    essere usate anche da linguaggi diversi.
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

     essere usate anche da linguaggi diversi.
Questo è ovvio, sarebbe assurdo se un buffer di caratteri non fosse meno
pesante e meno difficile da manipolare di una classe template ;-)
Il problema qui è che l'incapsulamento non è completo. Secondo la filosofia
OO, non dovrebbe avere importanza alcuna *CHI*, *COME*, *DOVE* e *QUANDO* ha
creato un oggetto; posto che la sua interfaccia sia nota, questa dovrebbe
più che sufficiente per utilizzarlo al meglio... i dettagli interni
dovrebbero restare, appunto, interni.
Massimo

dovrebbero restare, appunto, interni.
Questo non accade se non si usa late binding per *tutto*; nel
C++ questo non e' stato fatto per scelta di fondo.
Si puo' ovviamente implementare qualcosa del genere... ma
sicuramente questo non e' lo spirito con cui sono stati
progettati i template della libreria standard.


 progettati i template della libreria standard.
Appunto, come dicevo sopra, secondo me con una libreria standard simil-Java
il C++ diventerebbe veramente *IL* linguaggio.
Vorrei solo avere le conoscenze per poterla scrivere io...
Massimo

 bacata(oltre che ad avere ben poco di standard) ,tant'é che la
VC7 e' parecchio meglio. E prima che esca probabilmente lo sara' ancora di piu'.


     essere usate anche da linguaggi diversi.
Per l'uso con linguaggi diversi il problema resta. Se vuoi dei container
utilizzabili con tutti i linguaggi li devi fare a livello di piattaforma non a
livello di linguaggio.
COM::map ??


 problemi ovviamente non sussistono.
Se riallochi il buffer in un altro contesto hai lo stesso problema. Tale
problema pero' non sta nella definizione stadard di STL ma nell'implementazione
che non tiene conto di tutti i casi supportati dal OS specifico. Le soluzioni ci
sarebbero. Ma sono complesse. E MS non ha (per ora) interesse sufficiente a
creare una STL proprietaria che ne tenga conto. Quindi "compera" la STL da terze
parti e si concentra sul solo compilatore. Quando avremo VC conforme allora
forse questi aspetti verranno affrontati.


 std::map lo usi in un file solo: l'implemntazione della tua classe).
Bella idea, davvero.
Massimo

 progettati i template della libreria standard.
Questo secondo me perche' come dicevo non sono pensati per "emergere" a
livello di interfaccia tra classi e funzioni scritte dal programmatore.
Ciao,
Nicola

 il C++ diventerebbe veramente *IL* linguaggio.
No, sarebbe solo azzoppato.
Ciao,
Nicola

 COM::map ??
CORBA::map. :-)
Ciao,
Nicola

 CORBA::map. :-)
Come dicevo, a livello di piattaforma :-;






 No, sarebbe solo azzoppato.
Chiarisco questo punto. Non ho mai parlato di togliere i template, o abolire
la libreria standard, o addirittura di modifiche al linguaggio. Io parlavo
di partire dal C++ Standard comè definito ora e creare una libreria
object-based come quella del Java. E ovviamente dicendo questo non mi
riferisco solo a contenitori globali, ma a tutta quella condivisione di
caratteristiche possibile quando tutti gli oggetti derivano da una radice
comune, incluse quindi funzionalità per la RTTI e altre.
Tra l'altro, una simile libreria permetterebbe la specializzazione con una
facilità impressionante, proprio utilizzando i template.
Immaginiamo di aver definito una classe Object che funga da radice
universale, come in Java. E di aver definito una classe Vector che accetta
di contenere Object, e quindi tutto ciò che ne deriva. Ora, se vogliamo in
un sol colpo creare tutte le specializzazioni possibili di questa, basta
scrivere qualcosa come
template<class T> class specVector
{
    Vector _vect;
    // ovviamente innumerevoli altri membri, è solo un es.
    T& operator [] (int i)
    {
        return( (T&) _vect[i]);
    }
}
E riecco comparire la libreria di template. Solo che ora, se voglio una cosa
più generale, ad esempio un vettore che possa contenere di tutto (ma
contemporaneamente, non un solo tipo per volta) ce l'ho... e tutto al costo
di un cast. Non c'è nemmeno bisoghno di RTTI, perché il template, come
giustamente dici tu, viene espanso dal compilatore. E in questo caso può
essere espanso inline tranquillamente, visto che non fa altro che applicare
un cast (e lo stesso sarebbe per ogni specializzazione data a una libreria
scritta per gestire Object).
Il C++ resta tale e quale a prima, se vuoi i template ci sono anche quelli.
Tra parentesi, il C++ mi piace (molto) perché permette di fare tutto ciò che
fa il Java e molto di più, e allo stesso tempo non obbliga il programamtore
a fare nulla. Se torniamo all'idea di avere una classe radice comune per
ogni oggetto, questo è utile nella maggior parte dei casi, ma ad esempio in
Java comporta uno spreco se ho bisogno solo di raggruppare un po' di dati o
di svoglere qualche operazione. In C++ *POSSO* derivare tutto da un Object,
ma non sono tenuto a farlo nel caso in cui non mi serva.
Oggi molti sono abituati alla STL, ma molti altri la giudicano un male
necessario, ossia l'unico modo decente in cui si poteva implementare la
libreria standard del C++.
Io sarei stato per un altro approccio, simile a quello preso dal Java;
dopotutto, chi può dire quale sia migliore se non dopo anni di prove,
tentativi e raffinazioni successive dell'implementazione ? Pure la STL
all'inizio (e in alcuni casi anche tuttora) per prestazioni non brillava
decisamente...
Massimo

 come membro privato.
Ma in tal caso perdi l'interfaccia e ti tocca reimplementarla da capo,
creando una classe wrapper...
E poi il problema del distruttore virtuale qui non dovrebbe porsi, visto che
non parlava di estendere la classe, ma solo di derivarla per costringerla e
effettuare l'espansione del codice...
Massimo

 decisamente...
Io credo che un dato di fatto ci sia, ovvero il principio che
alternative completamente definite al momento della compilazione devono
essere definite al momento della compilazione: migliori prestazioni,
migliore sfruttamento della tipizzazione statica.
L'OO mi serve quando *effettivamente* voglio trattare a runtime entita'
di tipo diverso allo stesso modo sfruttandone gli elementi comuni; non
e' il caso dei contenitori omogenei. 
Ti consiglio di leggere "Multiparadigm Design for C++" di James O.
Coplien. Qui l'importanza di questa differenziazione e' presentata molto
chiaramente.
Ciao,
Nicola

*Mai* ereditare da una classe che non e' *scritta* come classe base. Non
ci sono eccezioni.
Nel caso dei contenitori STL hai poi il non trascurabile vantaggio di
evitare con poco sforzo di includerli nel tuo header file, incrementando
la velocita' di compilazione.
Ciao,
Nicola

 chiaramente.
Comunque il mio discorso voleva essere più di ampio respiro, la classe base
comune non servirebbe solo per poter gestire ogni suo derivato
polimorficamente, ma anche e soprattutto per implementare funzionalità
comuni.
Massimo

 generico che contiene tutto".
Non č impossibile in C++ costruire un container che possa ospitare
riferimenti a oggetti appartenenti a classi diverse, prive di qualsiasi
tipo di parentela o classe base comune. 
Ad esempio, se vogliamo un container che consenta di scrivere questo:
   container	c;
   c.push_back( new std::string("ciao") );
   c.push_back( new int(23) );
   c.push_back( new char('2') );
   std::string* sp = sort_of_cast<std::string>( c[0] );
   if( sp ) {
       cerr << *sp << endl;
    }
...possiamo implementarlo cosě:
 struct object { virtual ~object() { }; };
 template <class T >
 struct object_wrapper: public object
 {
    T* ptr;
    object_wrapper(T* p) : ptr(p) { }
 };
 struct container
 {
    std::vector<object*>	vect;
    template< class T >
     void push_back(T* p) {
       vect.push_back( new object_wrapper<T>(p) );
      }
     object* operator[](int i ) { return vect[i]; }
 };
 template< class T >
 T* sort_of_cast( object* o )
 {
     typedef object_wrapper<T>  wrap_type;
     wrap_type* wrap = dynamic_cast<wrap_type*>(o);
     return wrap ? wrap->ptr : 0;
 }
Max

     }
Decisamente carino... i template sono uno strumento potentissimo, lo so
bene. Non ho mai pensato nemmeno per un momento di abolirli :-)
Io contestavo solo la filosofia della libreria standard (a tutti i livelli,
non solo per i container), a cui credo un approccio più simile a quello del
Java potrebbe giovare molto (vedi la RTTI o la serializzazione).
Che poi il C++ abbia molti altri strumenti potenti e utili è fuor di
dubbio... ma una vera libreria object-based secondo me renderebbe il
linguaggio più coerente, elegante e maneggevole.
Prendi questo esempio: in un programma mi è capitato di avere una funzione
che, presa in input un'istanza di una classe X sottoclasse di A, doveva
allocare N istanze di X in un vettore. Ma il parametro formale era di tipo
class A, essendo ignota a compile-time la sottoclasse vera e propria da
usare. Come istanziare il tipo giusto ? In Java ho fatto
A array[] = null;
void init(A in,int n)
{
    array = new A[20];
    for(int i = 0;i < n;i++)
    {
        a[i] = in.getClass().newInstance();
    }
}
Sfruttando proprio le capacità di RTTI derivanti dall'architettura
object-based.
In C++ esiste un modo per fare una cosa del genere, e soprattutto, se
esiste, è comparabile per efficienza e semplicità d'uso a questo supporto
nativo offerto dalle librerie Java ?
Allo stesso tempo, la cosa più bella sarebbe avere tutti i vantaggi di una
simile libreria e nessuna delle costrizioni imposte dal Java. Se voglio
creare una classe che non abbia nulla a che fare con Object, in Java non
posso.
Massimo
P.S.
Forse questa è più una domanda da it.comp.java... ma se in Java volessi
usare una struttura dati che abbia una precisa dimensione in memoria, a
prescindere dai problemi di padding, non credo che potrei mai ottenere una
struttura esattamente come la vorrei, proprio per l'eredità obbligatoria da
Object che aggiungerebbe necessariamente qualcosa... ma forse qui mi
sbaglio.

 comuni.
Il punto e' che non esistono funzionalita' comuni a *tutte* le classi.
Ciao,
Nicola

 nativo offerto dalle librerie Java ?
Vedi, a me questo pare un esempio particolarmente contorto. In C++ avrei
dotato la classe A e le sue sotto-classi di un metodo clone(), ottenendo
una soluzione che a me pare piu' elegante.
Ciao,
Nicola

 niente. Io lo trovo un vantaggio.
Diciamo le stesse cose e non ci capiamo.
Ma l'hai letto l'ultimo paragrafo del mio messaggio ? :-)
Io adoro il C++ per la *QUANTITA'* di strumenti diversi che mette a
disposizione. Il Java è molto più restrittivo, non mi piace per questo.
Ma tra questi strumenti, penso che una vera libreria object-based
risulterebbe particolarmente utile.
Ma non ho mai detto di abolire i template, o l'ereditarietà multipla, o
altro...
Il C++ mi piace così. I template sono uno strumento molto potente che è
stato sfruttato a fondo. Ce ne sono altri che secondo me non lo sono, o non
come dovrebbero.
Tutto qui.
Massimo

 una soluzione che a me pare piu' elegante.
Già, ma avresti dovuto farlo virtuale e ridefinirlo per ogni sottoclasse...
quello che hai visto sopra invece è un supporto fornito implicitamente dal
linguaggio  comunque disponibile per ogni oggetto, senza dover scrivere
alcunché. Sono cose simili che vorrei in c++.
Comunque l'esempio era un utilizzo reale, non era particolarmente astratto,
può sembrare contorto ma mi è capitato di aver bisogno di una cosa simile.
Massimo

 può sembrare contorto ma mi è capitato di aver bisogno di una cosa simile.
Intendevo dire che e' molto chiaramente un "Javismo", che non ha senso
cercare di tradurre letteralmente in C++.
Ciao,
Nicola

 senza dover scrivere alcunché. Sono cose simili che vorrei in c++.
Se il problema è dover scrivere codice per implementare un newInstance()
in ogni nuova classe, puoi usare questa tecnica:
 template< class Derived >
 struct self_factory {
    Derived* newInstance() { return new Derived; }
    Derived* clone() { 
       return new Derived( static_cast<const Derived&>(*this)); }
 };
Quindi...
 class A: public self_factory<A>
 {
  };
Max

 come dovrebbero.
Ah, si comincia in questi mesi a utilizzare i template fino in fondo,
con esempi che fanno paura anche a me :-) Puoi dare un occhio su siti
come 
www.boost.org
 , 
www.oonumerics.org
 o leggere alcuni articoli del
C/C++ User's Journal (disponibile anche online).
Ciao,
Nicola

di un cast. Non c'è nemmeno bisoghno di RTTI, perché il template, come
vector<void*> mio_vettore;
può contenere di tutto (contemporaneamente, non un solo tipo per
volta)... e tutto al costo di un cast.
Anche se non vedo alcuna ragione per usare un contenitore che contiene
tanto mele quanto char* oppure frigoriferi :-)
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

kili.
se erediti privatamente hai di nuovo il problema del distruttore
virtuale. Cmq se dichiari i metodi inline non dovresti avere
indirezioni e overhead, dico bene?
anto


la velocita' di compilazione.
scusa, non ho capito questa frase: me la puoi spiegare meglio?


 indirezioni e overhead, dico bene?
Intendi dire metodi inline che fanno la ridirezione verso altri metodi di un
oggetto membro? Un piccolo overhead potrebbe esserci (il calcolo dell'offset
dell'oggetto). Comunque l'idea di partenza era EVITARE di avere i metodi inline!


 cercare di tradurre letteralmente in C++.
Era una situazione tremendamente concreta, avevo bisogno di creare N classi
di cui non sapevo il tipo esatto, solo il tipo base. Ma dovevano essere
create del tipo giusto, uguale a quello passato. In C++ che approccio
prenderesti per un problema simile ? Non lo dico per provocazione, mi
interesserebbe proprio saperlo.
Massimo

 C/C++ User's Journal (disponibile anche online).
Molta colpa è anche dei compilatori, attualmente usare i template in modo
avanzato è quasi impossibile per chiunque...
Massimo

   };
Scusa, stai dichiarando una classe A che deriva da una classe template
basata sulla stessa A ?
Sicuro che sia compilabile ?
Di ereditarietą ricorsiva non ne avevo mai sentito parlare :-)
Massimo

 tanto mele quanto char* oppure frigoriferi :-)
Pure io non avrei mai immaginato una ragione per dover allocare N classi di
un tipo ignoto e da riconoscere, fino a tre giorni fa...
Massimo

 interesserebbe proprio saperlo.
Sapendone cosi' poco l'unica alternativa mi pare quella della funzione
membro virtuale "clone()". Mi pare pero' il tipo di situazione nella
quale in C++ si tende a non infilarsi, proprio per il maggiore accento
sulla tipizzazione statica; per poterlo dire con maggior certezza
bisognerebbe conoscere il disegno ad un livello decisamente piu' ampio.
Avevo letto anche qualcosa a proposito del pattern Abstract Factory, che
dal nome potrebbe avere qualcosa a che vedere con questo tipo di
problemi, ma non mi ricordo i dettagli.
Ciao,
Nicola

   };
Si, anche se nel caso specifico e' un po' una menata, perche' deve
essere implementato ricorsivamente, e si avrebbe:
class B: public A, public self_factory<B> {};
e cosi' via. A quel punto il vantaggio del template non e' molto grande.
Ciao,
Nicola

Funziona, funziona, cosi' come funziona 
template <typename T> class C : T {};
Vedi cosa si puo' fare coi template? ;-)
Ciao,
Nicola

 avanzato è quasi impossibile per chiunque...
In parte e' vero, anche se evitando VC++ si riesce comunque a fare cose
discrete.
Ciao,
Nicola

 scusa, non ho capito questa frase: me la puoi spiegare meglio?
Se scrivi 
class A : public vector<int> {};
non puoi fare a meno di includere il file <vector> nel tuo header.
Idealmente scrivendo
class B {
  private:
    vector<int> * vi;
};
potresti limitarti a dichiarare vector nello header e includere <vector>
solo nel .cpp. In realta' per le classi della libreria standard questo
non e' consentito. Puoi aggirare il problema avolgendo vector in
un'altra classe:
class D;
class C {
  private:
    D * d;
};
class D {
  private:
    vector<int> v;
};
E' piu' chiaro?
Ciao,
Nicola

 wrote in message
news:3A8B92CA...@divalsim.it...

Come dice Nicola non e' chiaro il problema originale. Ovvero mancano
informazioni a livello di analisi e di design. Detto cosi' quasi tutti i pattern
creazionali potrebbero essere la soluzione: Abstract Factory, Builder, Factory
Method o Prototype (ovvero il famigerato metodo clone).
Molto dipende da perche' hai a compile time solo l'informazione sulla
interfaccia (classe base) e non sul tipo concreto. E da come ti viene comunicato
a runtime il tipo concreto.
Un meccanismo abbastanza generale sarebbe mappare l'informazione runtime sul
tipo concreto (che sia una stringa o un ID) alla classe da istanziare. Per
esempio con un dizionario indicizzato sull'informazione runtime e avente come
informazione o una istanza della classe da clonare, o una istanza di una
factory, o un puntatore ad una funzione che crea un'istanza della classe
concreta.


 nella libreria standard.
Vero. Ma in cambio si prestano molto bene alla generalizzazione. Ovvero ai
template. Infatti un uso "avanzato" dei template e' proprio quello di espandere
in maniera ottimizzata degli algoritmi matematici abbastanza complessi (tipo
calcolo matriciale).


 a runtime il tipo concreto.
Ok... il progetto era un simulatore di politiche di accesso a un database
condiviso, l'interfaccia DBManager definiva astrattamente un gestore di
accesso per questo database:
Interface DBManager
{
    public void beginread();
    public void beginwrite();
    public void endread();
    public void endwrite();
}
e le classi che la implementavano permettevano di realizzare varie
politiche.
Il database era diviso in partizioni, ognuna delle quali gestita da un
DBManager distinto per aumentare la concorrenza; tali oggetti venivano
conservati in un vettore di dimensione pari al numero di partizioni, e di
questo oggetti era noto a compile-time solo il tipo base: DBManager,
appunto.
La funzione di inizializzazione riceveva come parametro un oggetto di tipo
DBManager (il tipo esatto era ignoto) e doveva istanziarne N e assegnarli ai
singoli elementi del vettore. E ovviamente questi dovevao essere del giusto
tipo derivato. Ecco il codice Java:
class SharedDB
{
    // ...
    private DBManager[] DBM = null;
    public SharedDB(int part,DBManager dbm)
    {
        // ...
        DBM = new DBManager[npart];
        for(int i = 0;i < npart;i++)
            DBM[i] = (DBManager) dbm.getClass().newInstance();
        // ...
    }
}
Non ho dubbi che in C++ sia possibile implementare qualcosa di simile.
Ma il punto è proprio sul doverlo implementare, mentre in Java ogni oggetto
supporta automaticamente metodi simili (e altri) in virtù dell'ereditarietà
comune. E sopratutto di un miglior supporto RTTI, anche a livello di
linguaggio (vedi instanceof).
Massimo

 e' stata progettata da un matematico.
Non metto in dubbio che formalmente sia elegantissima.
Ma questo non vuol dire necessariamente che sia comoda e pratica da usare
;-)
Massimo

             DBM[i] = (DBManager) dbm.getClass().newInstance();
E' il pattern "prototype". Metodo "virtual DBManager* DBManager::clone()
const=0" da ridefinire nelle classi concrete come "DBManager*
ConcreteDBManager::clone() { return new ConcreteDBManager; }". Non mi dire che
e' una faticaccia!


Lo e' eccome, basta conoscerla.
Ciao,
Nicola

carente ;-)
scusa, ma continui a saltare da un argomento all'altro; stai
criticando il linguaggio o la STL? fino agli altri post credevo la
STL, ma adesso ti lamenti di una mancanza del linguaggio.


dell'oggetto). Comunque l'idea di partenza era EVITARE di avere i metodi inline!
hai ragione, stavo pensando ad un altra cosa.


E' piu' chiaro?
ok, grazie


 e' una faticaccia!
No, ma devo scrivere 5 metodi diversi per 5 implementazioni diverse. E anche
questo sarebbe banale, ma in linea di principio di implementazioni diverse
potrei averne anche trecento, che con le due righe di Java scritte sopra non
avrebbero problemi a istanziarsi.. e senza ridefinire alcunché nelle
implementazioni.
C'è (quasi) sempre un modo per aggirare un problema, ma una soluzione è
meglio ;-)
Massimo

 STL, ma adesso ti lamenti di una mancanza del linguaggio.
Innanzitutto, vorrei precisare che non sto "criticando" tanto per
polemizzare un po'... secondo me il C++ ha i suoi pregi e i suoi difetti,
così come il Java. Quest'ultimo è molto più "evoluto" come filosofia OO, ma
soffre (a mio parere) di una semplificazione eccessiva, ad esempio la
decisione automatica se usare passaggi per valore o riferimento. Non ho mai
capito perché se creo un array di 10 int ottengo 10 interi, mentre con un
array di 10 Object ottengo 10 *PUNTATORI* a Object. O meglio, per capirlo
l'ho anche capito (non si allocano oggetti se non con new), e mi ripugna un
po'. Ed è un esempio fra tanti. Il C++, d'altra parte, offre una potenza
ineguagliabile e un livello di "dettaglio" che il Java nemmeno si sogna, ma
soffre di alcune limitazioni nel suo supporto alla OOP. Questo è un dato di
fatto, quindi c'è poco da fare a meno di non modificare la definizione del
linguaggio. Però alcune (o forse molte) di queste limitazioni sarebbero
comunque aggirabili implementando appropriate librerie... che siano
effettivamente object-based però, e non si limitino a delle super-macro con
un po' di controllo dei tipi in più. Questo indipendentemente dal fatto che
poi i template siano potenti e utili, questo non si può negare... ma un
linguaggio OO non può avere solo quelli.
Almeno secondo me, ovviamente.
Massimo

linguaggio OO non può avere solo quelli.
Infatti attualmente i template costituiscono uno dei punti deboli del C++ "in
pratica", perché in teoria dovrebbero essere ben più potenti. E poi, chi ha
detto che il C++ ha solo quelli? E poi, la potenza e l'efficacia di un
linguaggio OO non sono determinati dal numero di costrutti disponibili. Il Java
è un po' come la "pappa pronta" dell'OOP, il C++ ne è invece il "cemento". Il
Java ti offre moltissime cose di alto livello, ma insieme anche molte
limitazioni. Una delle più ridicole a mio parere è il fatto che TUTTI gli
oggetti di Java debbano essere derivati da una classe unica. Il C++ non ti
obbliga a questo, ma te lo permette. In fondo, potrei decidere anche che la mia
"class Aria" non abbia niente a che fare con la mia "class Orecchio", quindi
perché legarle tra loro in una sorta di "finta parentela"?
Ciao
Domenico Barra

linguaggio OO non può avere solo quelli.
ma il C++ non ha *solo* quelli.
anto


Quello che appare strano nel tuo esempio e' che chi crea l'istanza
originale del tuo DBManager, e quindi conosce il suo tipo effettivo, non
crei anche le copie. Soprattutto dal momento che le copie vengono a
quanto pare create tutte insieme.
Ciao,
Nicola

 linguaggio OO non puň avere solo quelli.
Si puo' discutere sul modo giusto di implementare meccanismi di
programmazione generica, e certamente i template mettono particolarmente
in risalto le stramberie che il C++ ha ereditato dal C; cio' non toglie
che un linguaggio orientato alla tipizzazione statica, che voglia
definirsi completo e moderno, non puo' mancare di supporto a questo tipo
di paradigma.
Ciao,
Nicola

 obbliga a questo, ma te lo permette. In fondo, potrei decidere anche che la
mia
Spiegami in che modo il C++ ti permette di derivare tutti gli oggetti da una
classe unica.
Per esempio, se io avessi una classe chiamata Object da cui voglio che tutti gli
oggetti derivino, spiegami come faccio a derivare "unsigned long" da Object.


 da Object.
Non lo puoi fare nemmeno in Java, senza un wrapper... :-/
Massimo

oggetti derivino, spiegami come faccio a derivare "unsigned long" da Object.
L'hai voluto tu :-)
---------------------------------------------------------
class Object  {
   public:
       virtual const char *AmIAnObject() { return "Yes, I am an Object!"; }
};
class Unsigned_long : public Object {
        unsigned long int m_data;
    public:
        const char *AmIAnObject() { return "I'm derived from Object, so I'm
an Object!"; }
        Unsigned_long(unsigned long int x) : m_data(x) { }
        operator unsigned long int() { return m_data; }
        /*... implementi gli operatori +=, =, ++, --, il resto non ti servono
neppure (perdonami se ho tralasciato qualche operatore indispensabile) */
};
----------------------------------------------------------
Ora Unsigned_long deriva da Object, e non puoi dire che Unsigned_long non sia
uguale ad unsigned long, anzi ti sfotte pure, ribadendo che è anche derivata da
Object ;-)
Ciao
Domenico Barra

oggetti derivino, spiegami come faccio a derivare "unsigned long" da Object.
... L'hai voluto tu :-)
---------------------------------------------------------
class Object { };
class Unsigned_long : public Object {
         unsigned long m_data;
    public:
         Unsigned_long() : m_data(0) { }
         Unsigned_long(unsigned long x) : m_data(x) { }
         operator unsigned long() { return m_data; }
         /* poi implementi gli operatori =,++,--, la serie di +=,-=,^=,|=... e
credo tu abbia finito: scusami se ho tralasciato qualche operatore
indispensabile. */ 
};
----------------------------------------------------------
Contento? Ora Unsigned_long (che è uguale a unsigned long) deriva da Object.
Ciao
Domenico Barra

 Object ;-)
Si che posso dirlo. E lo dice anche il compilatore. Prova a usare sizeof o
typeid o a mischiare dei puntatori ai due tipi e vedrai! E prova a sostituire
Unsigned_long ad "unsigned long" in un contesto in cui esiste una catena di
conversioni fra cui una che coinvolge un'altra classe definita dall'utente.


conversioni fra cui una che coinvolge un'altra classe definita dall'utente.
Concludo: se vuoi un tipo che rappresenti un intero lungo senza segno e 
derivi da Object, allora devi usare quello. Usare unsigned long sarebbe una
incoerenza, sarebbe come dire: "voglio che il mio intero derivi da Object, ma
voglio che non derivi da Object". Questa è una contraddizione. Una volta creato
il wrapper, usi quello; il tipo built-in è solo una realtà del compilatore, il
programmatore non la conosce :-)
E' stato piacevole scambiare pareri con te.
A presto :-)
Domenico Barra

oggetti derivino, spiegami come faccio a derivare "unsigned long" da Object.
class Object { /*...*/ };
template<class T> class object_derived: public Object {
	T t;
public:
	object_derived(T tt): t(tt) { };
	operator T { return t; };
	/* operator +=, -= ecc. */
};
#define int object_derived<int>
#define double object_derived<double>
/* ecc. */
però sinceramente non saprei come comportarmi con unsigned e long (a
meno di non usare ulong e simili)


 programmatore non la conosce :-)
Sia pure. Ma esiste del codice che se usi unsigned long predefinito compila e se
usi il tuo oggetto non compila. Nelle catene di conversione lo standard tratta
esplicitamente in modo diverso i tipi predefiniti dai tipi definiti dall'utente.
E' questo che volevo sottolineare.


 unsigned long int* Unsigned_long::get_pointer();
O, ancora meglio:
unsigned long int * Unsigned_long::operator & ();
Ciao,
Nicola

A questo punto della discussione, che per altro mi pare diventata un po'
sterile, mi pare doveroso domandare a te e Massimo:
In base a quali criteri attribuite o meno la patente di OO-ita' a un
lingaggio?
Questi criteri da dove provengono? (riferimenti, per favore)
Ciao,
Nicola

unsigned long int * Unsigned_long::operator & ();
Gią, mi č venuto in mente dopo aver spedito il messaggio. Frutto di una mia
antica convinzione, secondo la quale l'operatore & poteva essere
sovraccaricato solo in forma binaria. Poi venne B.Stroustrup ad eliminare tale
convinzione, ma evidentemente gli strascichi si fanno ancora sentire. E' una
dimostrazione di come notizie sbagliate apprese da principiante possano
protrarre i loro effetti molto a lungo :-/
Ciao
Domenico Barra

 protrarre i loro effetti molto a lungo :-/
Potremmo chiamarla HSS.
Ovviamente HSS e' un TLA.
Ovviamente TLA sta per "Three Letter Acronym".
Ovviamente HSS sta per "Herbert Schildt Syndrome".
:-)  <-- questo non e' un TLA


 wrote in message
news:3A93815E...@divalsim.it...

Sono d'accordo con te che la discussione stia diventando sterile.
Non ho una definizione vera e propria (anche perche' non ho ancora trovato una
vera definizione di OO, ho solo trovato la definizione di vari concetti
dell'OO).
In generale, come ho gia' detto, tendo a considerare due aspetti: uno e' il
supporto del linguaggio ad un design OO realizzato senza tener conto del
linguaggio di implementazione. In questo senso praticamente non esiste nessun
linguaggio completamente OO (che io sappia). L'altro e' l'uso fatto negli anni
in cui la OO veniva "definita" (ammesso che sia poi stata definita in maniera
definitiva) dei vari linguaggi per illustrare i concetti. Ovviamente con
l'aumento della diffusione del C++ questo linguaggio ha avuto un ruolo sempre
maggiore ed e' diventato il linguaggio di preferenza per illustrare tutti quei
casi che e' in grado di supportare. Questo semplicemente perche' e' certamente
il linguaggio piu' conosciuto. Ma ovviamente ben pochi userebbero il C++ per
illustrare la tipizzazione dinamica o lo Smaltalk 80 per illustrare
l'ereditarieta' multipla. Inoltre alcuni linguaggi, per esempio Eiffel,
Smalltalk, CLOS etc., nascono con l'OO come "target" principale. Ma nota come
Eiffel e Modula 3, pur avendo Pascal come "ispirazione", di fatto non cerchino
assolutamente di essere compatibili con Pascal a scapito dell'OO a differenza di
quello che fa C++ con il C.
Esempi di features che possono essere previste a livello di design astratto ma
che non sono sempre supportate dai linguaggi (salvo modifica del design o
meccanismi di implementazione indiretta) sono:
- Uso della tipizzazione dinamica degli oggetti: che per esempio il C++ non
supporta completamente.
- Uso della tipizzazione dinamica dei messaggi (metodi, in C++): che per esempio
in C++ e' solo parzialmente supportata dai puntatori a metodo.
- Riflessivita': che normalmente e' carente in tutti i linguaggi in cui e'
carente la tipizzazione dinamica.
- Rappresentazione uniforme: mi riferisco al fatto che i tipi predefiniti siano
trattati allo stesso modo dei tipi definiti dall'utente e al fatto che, per
esempio, codice e classi in se non siano oggetti in linguaggi come il C++ (e
molti altri). Lo sono invece in Smalltalk e simili. Naturalmente questo ha una
grossa influenza sulla riflessivita'.
- Derivazione multipla: credo che la discussione teorica su questa feature del
C++ non sia ancora terminata. Da quello che so quasi tutti sono concordi nel
dire che e' utile e permette dei design piu' chiari e puliti, ma nello stesso
tempo sono pochi quelli che la considerano parte necessaria del concetto di OO.
Non sono un teorico dell'OO e quindi non mi pronuncio sul fatto che sia
necessaria, ma anche io concordo sul fatto che e' utile.
- Generici: ovvero i template in C++, i generic in ADA etc.
- Cambio della classe concreta a runtime: spesso usato per modellare ad alto
livello le macchine a stati. Non certo facile da implementare in linguaggi con
tipizzazione puramente statica come il C++ o Eiffel e non direttamente
supportato neppure da molti linguaggi a tipizzazione dinamica.
- multimetodi: ancor meno supportati dai linguaggi "classici" (supportati pero'
in CLOS e supportabili con un pochino di fatica in Smalltalk, da quello che ho
sentito dire). La feature-set del C++ che piu' si avvicina a supportarli e' un
meccanismo basato su template+overloading+friend con l'obbligo di template
instantiation esplicita. Non molto ma sempre meglio di nulla.
Vi certamente altre "feature" che sono utilizzate a livello di design astratto
ma che sono praticamente inimplementabili nella maggior parte dei linguaggi. E
non e' semplice distinguere con esattezza quali "fanno parte dell'OO" e quali
no. Come dicevo la definizione di OO e' abbastanza "fuzzy". In teoria l'OO e'
descritta come una filosofia basata su pochi concetti fondamentali, dai quali
pero' si possono derivare una quantita' incredibile di design diversi e di
corollari, non sempre implementabili. Proprio per questo, ad un certo punto
della fase di analisi/design (prima e' meglio e' anche se farlo "a priori"
spesso e' piu' uno svantaggio che un vantaggio) bisogna "decidere" quale (o
quali) linguaggi verranno usati.


 dell'OO).
Quoto una frase quasi a caso per associarmi in pieno a tutto il post, e
preciso che non ho pregiudizi pro o contro il C++ (o il Java), ritengo
semplicemente che nessuno dei due sia granché OO. Il C++ è potente ma troppo
limitato da alcune scelte progettuali (essenzialmente la compatibilità C
totale), il Java invece è progettato meglio ma troppo limitato, puoi fare
solo quello che i creatori hanno previsto che tu debba poter fare, e con
l'intento di semplificare la vita al programmatore astrae eccessivamente dai
dettagli tecnici della macchina. E se per caso ne hai bisogno per fare
qualcosa di non previsto, non c'è verso di metterci le mani sopra.
Tutto questo ovviamente parlando solo dei linguaggi in quanto tali, la VM
non c'entra nulla anche se poi nella realtà va pesantemente a discapito del
Java.
Massimo


Potremmo definirla NYSCPPSWTCTEBCIDOM,
ovvero: Not Yet Standard C Plus Plus Syndrome, With The Consequence That Every
Book Contained Its Dose Of Mistakes.
per chi non conosce l'inglese:
Sindrome da C++ non ancora Standard, con la conseguenza che ogni libro
conteneva la sua dose di sciocchezze.
Questo era un ELA (Eighteen Letter Achronym) :-)
Comunque ritengo personalmente che HS sia uno degli autori che all'epoca
generavano piů confusione. Tuttavia č un caso particolare, perché riesce a
generarne tanta anche oggi che uno Standard c'č.
Ciao
Domenico Barra


Questa è una cosa che desidererei tantissimo anche io.
Una Libreria Standard POSIX C++.
Delle classi standard per i thread e per tutto il resto....
Questa libreria dovrebbe essere costruita sulla base della libreria
Standard C++.
Ciao
Manlio.

 Standard C++.
Assolutamente d'accordo. Avrei anche un nome: POOSIX. Se non fosse che
so che non ci dedicherei molto tempo, suggerirei di "lanciare" un
progetto aperto.
Ciao,
Nicola

 Sei qui per restare?
Il tono della domanda è ambigua :).
Speravate di esservi liberati di me?.
Ad ogni modo sono (purtroppo) occupato con una vacanza forzata
dovuta allo Stato (leggi "sto facendo il militare"), quindi posso
scrivere solo quando sono in licenza.

Ci sono gia delle librerie Open Source che si occupano di alcune
problematiche, servirebbe 'solo' mettere le cose insieme....
Ciao
Manlio Perillo