Newsgroup: it.comp.lang.c++
Titolo: ***Questa è la prima volta***

Salve a tutti.
E' la prima volta che mi affaccio su questo ng
in quanto, dopo anni di programmazione con
il linguaggio C in ambiente DOS, mi sono finalmente
decisa a apprendere ed utilizzare il Visual C++ ver.5.
e a lavorare in Windows 95.
Non ho molta pratica della programamzione
in Windows né del mondo degli oggetti,
ma sto studiando. Stranamente, mi trovo
abbastanza a mio agio nel C++. Sarò
patologica ?
Finora mi sono esercitata nel lurking e da
quello che ho visto, credo di essere una delle
poche femminucce. Spero che questo particolare
non sia influente !  :-)
(se c'è qualche altra rappresentante del
gentil sesso la prego di accettare le mie scuse).
Colgo l'occasione per salutare tutti i presenti
e per avvisarvi che fra poco mi farò sentire...
con le mie lamentevoli richieste di aiuto ! 
E inizio subito: qualcuno ha per caso qualche
sorgente piccino piccino (eventualmente 
documentato) abbastanza didattico ?
O qualche consiglio per chi ha appena
installato VC++ e non sa cosa fare ? :-)) 
Intanto grazie a tutti.
                                    *Milla

Ciao Milla,
e benvenuta sul NG.
Tra gli esempi del VisualC++, ci sono tutorial per il C e per il CPP (MFC),
se non sbaglio si chiamano rispettivamente Generic e Scribble.
cioa, Franco.
Franco Torrini - Software Engineer - 
f.to...@virtuart.it
VIRTUART - C.C.D. Creative Computer Design S.p.A.
Via di Quarto Annunziata, 80/b - 00189 Rome, Italy
Tel. 
+39 06 33076638
 - Fax. 
+39 06 33076670
Web: 
http://www.virtuart.it

installato VC++ e non sa cosa fare ? :-)) 
Non usare le MFC. Per imparare e' deleterio (in ambito lavorativo purtroppo
la questione e' diversa n.d.p.). E' vero che con le MFC riesci a costruire
un programma funzionante in 5 minuti, ma poi devi studiare per impare a
usare le MFC senza avere nel contempo imparare realmente ad usare il S.O.
Se puoi usa NT invece che Win9x perche' e' piu' stabile (quando giocherai
con il multithreading capirai, n.d.p.). Se riesci a recuperare l'SDK
troverai qualche 100 di Mb di esempi. L'Help (spesso mediocre come qualita',
e buono in pochi settori n.d.p.) dell'SDK e' poi indispensabile. Il VC++
dovrebbe averlo. Non ne sono sicuro perche' io mi installo comunque l'ultima
versione dell'SDK, quindi ce l'ho comunque.
Un posto dove guardare e' nel sito FTP dell'Infomedia (vai *credo* su
http://www.infomedia.it
 ), e scaricati qualche sorgente. Essendo Infomedia
una casa editrice di programmazione a tutti i sorgenti che troverai un
articolo collegato (non dovrei dirlo per un problemi di diritti d'autore, ma
alcuni di quei articoli si trovano in rete).
Sono di parte, ma se provi/trovi il sito dell'infomedia ti consiglio di
scaricarti i sorgenti di "MultiDesk" (CP Set. 98). Multithreadind, Mutex,
Thread di WatchDuck, un poco di grafica e di starnazzature. So che un
giovane lettore ci sta pure lavorando per la versione migliorata.
+++
Dimenticavo, cerca di procurarti il service pack per il VC++.
Autori consigliati: Prosise se decidi di usare le MFC, Richter e Thompson
d'annata comunque, evitare Petzold (a 32 bit e' un professore incapace
n.d.p.), e le guide di P.Norton (non le scrive piu' lui da quando sta ai
tropici con i soldi della Symantec n.d.p.).
--- (Elimina il papero per le repliche) ---

tropici con i soldi della Symantec n.d.p.).
Su questo, hai secondo me sacrosanta ragione -- e` un pezzo che
le guide di Norton non valgono praticamente piu` nulla, ahime`.
Alex

le guide di Norton non valgono praticamente piu` nulla, ahime`.
Per me le case che fanno buoni libri sono UTET, Prentince Hall, McGraw Hill,
Telecom (alcuni), Microsoft, O'Relly.
Anzi, per me la UTET ultimamente ha fatto uscire tre bombe con i due
Tanenbaum e il Russel&Norvig. Con il Solom della Microsoft Press il meglio
dei libri letti nel 98. 
Spero che l'UTET faccia uscire anche i rimanenti Tanenbaum.


--- (Elimina il papero per le repliche) ---
Come animalista convinto, nonche` patito di Disney e di PK,
mi rifiuto di eliminare paperi; preferisco replicare sul gruppo.
Alex

 preferisco replicare sul gruppo.
Meglio.


papero...@tin.it
 (Davide Quack) writes:
 
   Le tue (che tue non sono) TRACE no. Ti infilano delle NOP che tu *speri* che
   il compilatore bravo ed intelligente tolga. 
   [...]
 
   > per distinguere la "compilazione per
   >debug" (in cui assert valuta il suo argomento, e termina l'esecuzione
   >con messaggio d'errore se falso) da quella "ottimizzata" (in cui
   >assert "sparisce", e NON porta NESSUN overhead di esecuzione).
 
   Veramente non sparisce. In alcuni casi vengono inseriti dei NOP.
Vuoi dire  che ci sono  compilatori che non  ottimizzano una assert  fino a
farla  sparire  del  tutto?   Che  compilatori  sono?  E  in  che  casi  si
comportano cosi`?

comportano cosi`?
E` quello che ha detto; non so se e` quello che voleva dire.  Secondo
me e` un'affermazione "allo stesso livello tecnico" della maggioranza
di quelle che ha fatto; vedremo se riesce a portare dati d'appoggio,
cioe`, specifici esempi di compilatori/casi in cui:
    // primo blocco di codice
    assert(qualcosa);
    // secondo blocco di codice
produce codice diverso ("inserendo dei NOP") da:
    // primo blocco di codice
    // secondo blocco di codice
nella compilazione con NDEBUG (il define standard, C e C++, che
richiede di "far sparire" le assert dal codice generato).
Alex

 non sei qualificato per discutere di C e C++...
Va bene, ci sono pure casi in cui le macro servono, ma non si può negare che il
loro uso sia stato scoraggiato sin dalle prime versioni del C++, dallo stesso
Stroustrup, e che diversi costrutti del C++, e anche del C, siano nati *anche*
per limitare l'uso delle macro (enum, const, funzioni inline). E'
opinione largamente condivisa (anche da te, mi pare) che le macro vadano usate
SOLTANTO in caso di effettiva necessità. Più in generale, penso che tutte le
ottimizzazioni
(soprattutto quelle "spinte") vadano fatte solo se effettivamente ne sussiste
l'esigenza, ossia quando la velocità è un fattore critico oppure quando
l'aumento dell'efficienza si traduce in un effettivo e consistente miglioramento
qualitativo per l'utente. Negli altri casi ritengo sia meglio privilegiare
(mi ripeto, lo so) chiarezza, semplicità e manutenibilità del codice.
In ogni caso, senza entrare nel merito dell'uso delle macro in ATL,
che non conosco, mi pare che in generale quando si vedono TROPPE macro, possano
nascere dei legittimi sospetti... (vedi l'esempio precedente riferito a
MAKEINTRESOURCE, che esiste a causa della cattiva impostazione delle funzioni
con cui viene usata).
Saluti
Paolo

Discussione interessante, ma al solito, ripercorre i classici temi delle
guerre di religione. Per chi programma non e' necessariamente valido
utilizzare solo questo o solo quello, bensi utilizzare entrambi (a
seconda delle necessita') e arrivare, con il tempo e l'esperienza, a
conoscerne i pregi (?) e i difetti in modo da saperli sfruttare al
meglio.
Per chi fosse interessato consiglio la lettura di
http://www.relisoft.com/libs.html
che riporta (contro MFC e OWL) un tutorial sullo sviluppo di un mini
"framework" C++ basato sulle API Win32.
Personalmente, ho iniziato a programmare per Win quando ancora non
esistevano ne MFC ne OWL, quindi semplici WinAPI. Poi con l'uscita,
prima di OWL e poi di MFC, ho cercato di sfruttare la facilita' con cui
questi FW (?) permettevano di creare nuove applicazioni. Chiaramente,
con il tempo ho avuto modo di approfondirne la conoscenza e quindi
identificarne i limiti. Questo non vuol dire che le ho abbandonate, ma
semplicemente, che ho imparato ad utilizzarne le componenti che mi
servivano mentre ne estendevo le funzionalita' (sfruttando le WinAPI)
con mie componenti che ne compensavano (nei miei casi specifici) i
limiti.
Quindi, ritengo che il programmatore novizio non debba essere confinato
all'utilizzo di WinAPI senza comunque approfondire le MFC (o
quant'altro), in quanto, se la progammazione viene fatta per classi (ad
oggetti), lo stesso programmatore si trovera' a dover sviluppare il
proprio FW attorno alle WinAPI senza peraltro averne la capacita'.
Sicuramente, con il tempo il novizio arrivera' ad avere la necessaria
esperienza per compensare limiti e difetti magari sviluppandosi un
proprio FW (lavoro peraltro lungo e complesso sia per lo sviluppo che -
in particolar modo - per la successiva manutenzione).
Considerazione finale: tutto serve per imparare, specie gli errori (:-)
degli altri.
massimo

Mi accodo alla discussione tra Alex Martelli e Paolo Aiello sull'utilita' di
utilizzare MFC da parte di un novizio solo per qualche considerazione.
Se il novizio e' un novizio di programmazione farebbe meglio ad iniziare con
altri linguaggi.
Se e' un novizio di programmazione sotto Windows secondo me farebbe meglio
ad iniziare scrivendo programmi console per lasciare fuori tutti i problemi
derivanti dall'interfaccia grafica e soprattutto dalla programmazione ad
eventi. Una volta acquisita la dimestichezza con il linguaggio potrebbe
passare ad applicazioni Windows vere e proprie.
Per quanto riguarda l'uso di MFC io la ho da poco abbandonata ed ho iniziato
a scrivere, insieme a mio fratello Angelo, una libreria per conto mio. Trovo
che MFC sia complicata, pesante, mal progettata e con un mucchio di
limitazioni (as es. sul suo uso con il multithreading). Inoltre ha una curva
di apprendimento lunghissima.
Secondo me se non e' il massimo per un "non novizio" figuriamoci per un
novizio!
All'inizio ti sembra di aiuto perche' ti costruisce (grazie ai wizard) per
intero lo scheletro dell'applicazione ma poi piano piano ti accorgi che ogni
cosa che vuoi fare la devi fare in quel modo e non in quell'altro, che le
cose apparentemente semplici diventano complicate e soprattutto che non hai
subito la visione completa del funzionamento del programma (dov'e' finito il
main!).
E' chiaro che se un novizio vuole iniziare scrivendo un'applicazione
multi-document...
Ciao.
Antonio Donatiello

 
Dipende molto dal dominio in cui dovra' sviluppare.
Se parte semplicemente per imparare a programmare, senza alcun obiettivo
immediato, allora la tua indicazione e' corretta ed il novizio farebbe
meglio (se interessato alla progammazione OO) a rivolgersi verso altri
lidi (che non sono necessariamente piu' semplici, ma piu' vicini ai
principi OO).
Se, al contrario, il novizio deve applicare quello che impara ad uno
specifico dominio (magari perche' e' stato assunto come primo impiego in
una azienda che opera in un determinato settore) allora la scelta del
linguaggio puo' essere obbligata.
Forse, il novizio, dovrebbe appoggiarsi ad un tutor che lo possa guidare
nelle scelte che dovra' operare.
Resta la considerazione che se il novizio e' costretto (per necessita'
contingenti) a sviluppare rapidamente un'applicazione (con linguaggio
obbligato) la via MFC e', pur con tutte le sue limitazioni, la piu'
rapida. Comunque, il novizio, quando non sara' piu' tanto novizio (un
tot di KLOC nel futuro) sara' in grado di rendersi conto personalmente
di tutte le limitazioni che presentano i tool che usa. Magari cambiera'
non solo il FW, ma addirittura il sistema operativo. Tutto e' possibile.
massimo

quant'altro),
Il punto non mi sembra fosse winapi vs framework, poiche` se il novizio
e` tale nei riguardi della programmazione windows qualunque strada
sarebbe valida: con le api prima o poi dovra` averci a che fare in quanto
il framework solitamente non copre tutto (o comunque non sempre nel
migliore dei modi), d'altronde l'uso di un framework puo` (se ben fatto)
consentire un approccio graduale alle api (che essendo molte possono
generare un senso di smarrimento), magari evitando l'uso di wizart.
Se invece il novizio e` tale nei confronti del linguaggio, non mi sembra il
caso di una simile discussione... il C++ e` sufficientemente complesso da
sconsigliare un duplice e contemporaneo approccio al linguaggio e alle
caratteristiche di un ambiente (intendendo per ambiente sia il solo specifico
sistema operativo che la coppia s.o.-framework).
Paolo
----------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
  e-mail: 
mar...@cli.di.unipi.it
 
----------------------------------------------------------

funzioni con cui viene usata).
Chi ha progettato le tante funzioni dell'API di Windows che accettano
un identificatore di risorse avrebbe sicuramente potuto scegliere di
raddoppiarle in numero, avendo, per ciascuna, una versione che accetta
solo un intero, e un'altra che accetta solo una stringa; sarebbe stata una
scelta molto discutibile, pero`, visto che di funzioni, nelle API, ce ne sono
gia` fin troppe.  Supponiamo, dunque, che le effettive API di Windows siano
esattamente quelle che sono, e vediamo come il progettista di un
framework puo` affrontare questo problema.
In C++ si potrebbe proporre una soluzione identica, ma basata su
inline invece che su macro, magari con un overload:
inline const char*
Resource(short i)
{
    return reinterpret_cast<const char*>(i);
}
inline const char*
Resource(const char* pc)
{
    return pc;
}
cosi` l'utente puo` uniformemente dire Resource(ID_PIPPO) e/o
Resource("Pippo") e tutti vivono felici e contenti.  Il valore aggiunto
rispetto alla macro e` modesto, ma non nullo.
Un approccio alternativo sarebbe di "sdoppiare" ogni "vera"
funzione delle API, che prenda in identificatore di risorse, in
due "finte" funzioni in overload -- una che prenda un const
char*, e una che prenda un int; entrambe chiamerebbero
poi la "vera" funzione con eventuali cast.  Purtroppo, per fare
questo bisogna cambiare il nome usato, perche` in C++ non
si puo` fare l'overload di una funzione extern "C"; e allora, gia`
che si cambia il nome, tanto vale adottare un approccio usabile
anche in C (supponendo INLINE sia una macro per compilazione
condizionale, che si espanda in C++ a inline, in C con estensioni
a __inline, in C standard a nulla pagando il prezzo a runtime):
INLINE HRSRC FindResourceStr(HMODULE hModule,
    LPCTSTR lpName, LPCTSTR lpType)
{
    return FindResource(hModule, lpName, lpType);
}
INLINE HRSRC FindResourceRid(HMODULE hModule,
    short id, LPCTSTR lpType)
{
    const char* sid = reinterpret_cast<const char*>(id);
    return FindResource(hModule, sid, lpType);
}
eccetera, eccetera.
Se valga o meno la pena di scrivere tutte queste versioni
alternative, mah, "passo"; la type-safety e` importante, ma
le grosse collezioni di definizioni che portano solo "zucchero
sintattico" o poco piu` vanno generalmente guardate con
il dovuto sospetto, e non mi e` chiaro qui quale forza prevalga
(probabilmente, oggi, la seconda, considerando i milioni di
programmatori che gia` sanno che la funzione da chiamare
si chiama FindResource -- diverso avrebbe potuto essere
il discorso quando usci` Windows 1.0, ma all'epoca gli include
di Windows parevano gia` esageratamente grandi...:-).
Alex

 
[snip]
Vista la quantita' di righe che hai scritto e vista l'ora in cui hai
spedito il messaggio, presumo che tu abbia saltato il pranzo :-)
Scherzi a parte, complimenti per la estesa disamina di ogni argomento.
C'e' chi ha detto: "molti nemici, molta gloria"
massimo

C'e' chi ha detto: "molti nemici, molta gloria"
Beh, quelle che hanno "molti nemici" (e in buona parte se li
meritano!-) sono le MFC; e in effetti, non e` che io mi qualifichi
come "loro amico", cosi` come, mi pare di capire dai post tuoi,
neppure tu le "adori"... magari e` piu` una questione di "giudizio
tecnico bilanciato ed articolato" -- capacita` di percepire con
chiarezza i limiti dell'ambiente, ma anche i suoi vantaggi, e di
soppesare gli uni e gli altri a seconda delle situazioni, piuttosto
che cedere all'ovvia tentazione di "condannare a tappeto".
Comunque, se non si deve "far d'ogni erba un fascio" rispetto
alle MFC (sino a ridicoli estremi palmipedi tipo "abbandonarle
perche` un certo release aveva un memory leak in CString"...),
a maggior ragione non bisogna farlo rispetto a chi le condanna --
fra lo starnazzare di un papero che sostiene di essere una campana,
e i giudizi tecnici ponderati e difendibili di un Aiello, vedo un solco
molto piu` grande che fra questi ultimi e le valutazioni mie, anche
se le conclusioni che traggo io, e quelle di Aiello, possono differire!
Alex

E` quello che ha detto; non so se e` quello che voleva dire.
Purtroppo e' quello che volevo dire.
#define _ASSERT(expr) ((void)0)
non genera codice inutile in realise.
++++++++++++++++++++++++++++++++++++++++++++++++++
Per motivi imperscrutabili stavo pensando a:
#define for(exp) if(false); else for(exp)
int __cdecl main(void)
{	  
	int j = 1;
	for( int i; i < 10; ++i)
		++j;										 
	for(int i; i < 9; ++i)
		--j;
	return(0);
}
che puo' generare senza ottimizzazione codice del tipo: 
(if(false) non viene tolto)
	TITLE	F:\TEMP\Papero\main.cpp
	.386P
_main	PROC NEAR
; 5    : {	  
	push	ebp
	mov	ebp, esp
	sub	esp, 12					; 0000000cH
; 6    : 	int j = 1;
	mov	DWORD PTR _j$[ebp], 1
; 7    : 
; 8    : 	for( int i; i < 10; ++i)
	xor	eax, eax
	test	eax, eax
	je	SHORT $L217
	jmp	SHORT $L222
$L217:
	jmp	SHORT $L220
$L221:
	mov	ecx, DWORD PTR _i$219[ebp]
	add	ecx, 1
	mov	DWORD PTR _i$219[ebp], ecx
$L220:
	cmp	DWORD PTR _i$219[ebp], 10		; 0000000aH
	jge	SHORT $L222
; 9    : 		++j;										 
	mov	edx, DWORD PTR _j$[ebp]
	add	edx, 1
	mov	DWORD PTR _j$[ebp], edx
	jmp	SHORT $L221
$L222:
; 10   : 
; 11   : 	for(int i; i < 9; ++i)
	xor	eax, eax
	test	eax, eax
	je	SHORT $L223
	jmp	SHORT $L228
$L223:
	jmp	SHORT $L226
$L227:
	mov	ecx, DWORD PTR _i$225[ebp]
	add	ecx, 1
	mov	DWORD PTR _i$225[ebp], ecx
$L226:
	cmp	DWORD PTR _i$225[ebp], 9
	jge	SHORT $L228
; 12   : 		--j;
	mov	edx, DWORD PTR _j$[ebp]
	sub	edx, 1
	mov	DWORD PTR _j$[ebp], edx
	jmp	SHORT $L227
$L228:
; 13   : 
; 14   : 	return(0);
	xor	eax, eax
; 15   : }
	mov	esp, ebp
	pop	ebp
	ret	0
_main	ENDP
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mentre lasciando che il compilatore ottimizzi diventa
_main	PROC NEAR					; COMDAT
; 6    : 	int j = 1;
; 7    : 
; 8    : 	for(int i = 0; i < 10; ++i)
; 9    : 		++j;										 
; 10   : 
; 11   : 	for(int i = 0; i < 9; ++i)
; 12   : 		--j;
; 13   : 
; 14   : 	return(j);
	mov	eax, 2
; 15   : }
	ret	0
_main	ENDP
ovvero il compilatore tratta i due cicli for come una costante.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Se invece uso:
int __cdecl main(void)
{	  
	int j = 1, i = 0, z = 0;
	for(i = 0; i < 10; ++i)
		for(z = 0, j++; z < 3; ++z)
			j++;
	return(j);
}
il VC ottimizza di meno
_main	PROC NEAR					; COMDAT
; 3    : 	int j = 1, i = 0, z = 0;
	mov	eax, 1
	mov	ecx, 10					; 0000000aH
$L219:
; 4    : 
; 5    : 	for(i = 0; i < 10; ++i)
; 6    : 		for(z = 0, j++; z < 3; ++z)
	add	eax, 4
	dec	ecx
	jne	SHORT $L219
; 7    : 			j++;
; 8    : 
; 9    : 	return(j);
; 10   : }
	ret	0
_main	ENDP
+++++++++++++++++++++++++++++++++++++++++++++++++++
Stessa cosa con:
inline int Add(void)
{
	int j = 1, i = 0;
	for(i = 0; i < 4; ++i)
		j++;
	return(j);
}
int __cdecl main(void)
{	  
	int j = 1, i = 0;
	for(i = 0; i < 10; ++i)
		j += Add();
	return(j);
}
_main	PROC NEAR					; COMDAT
; 25   : 	int j = 1, i = 0;
	mov	eax, 1
	mov	ecx, 10					; 0000000aH
$L226:
; 26   : 
; 27   : 	for(i = 0; i < 10; ++i)
; 28   : 		j += Add();
	add	eax, 5
	dec	ecx
	jne	SHORT $L226
; 29   : 
; 30   : 	return(j);
; 31   : }
	ret	0
_main	ENDP
++++++++++++++++++++++++++++++++++++++++++++++++
Mentre:
inline int Add(void)
{
	int j = 1, i = 0;
	for(i = 0; i < 4; ++i)
		j++;
	return(j);
}
int __cdecl main(void)
{	  
	int j = 1, i = 10;
	if(i--)
	{
		j++;
		j += Add();
	}
	return(j);
}
_main	PROC NEAR					; COMDAT
; 44   : 	int j = 1, i = 10;
; 45   : 
; 46   : 	if(i--)
; 47   : 	{
; 48   : 		j++;
; 49   : 		j += Add();
; 50   : 	}
; 51   : 
; 52   : 	return(j);
	mov	eax, 7
; 53   : }
	ret	0
_main	ENDP
Torna ad essere ottimizzato. 
+++++++++++++++++++++++++++++++++++++++++++++++
Chi ci capisce e' Bravo


 che cedere all'ovvia tentazione di "condannare a tappeto".
Condannare...mah, siamo in uno stato garantista, e poi puo' sempre
accadere che
ci si venga a trovare al poso del condannato, quindi...meglio predonare
e poi tenere d'occhio il soggetto.
In questo caso il soggetto sono le MFC (degnamente accompagnate da quasi
tutti gli altri FW che ruotano attorno alle API di Windows).
Qui non si tratta di essere guelfi o ghibellini, ma semplicemente di
sfruttare quello che fa piu' comodo. Le MFC ci sono. Certo, dal punto di
vista progettuale sono un esempio da non seguire (ma, e' valida la
scelta commerciale di non allontanarle troppo dalle API in modo da
catturare con facilita' tutti quelli che fino al giorno prima
utilizzavano solo Win16/32), e solo la mia tastiera sa veramente quanto
vorrei che sotto l'albero di Natale apparisse un vero FW, ben fatto e
ben progettato. Pero', per essere sincero, mi ritrovo ad utilizzarle
estesamente dato che svolgono "sufficentemente" il loro compito e dato
che, con un po, di pratica sono arrivato a rendere indipendenti l'UI dal
dominio dell'applicazione (grazie anche a M.Fowler).
In sostanza, conosco il mio nemico (n.b. un nemico lo controlli, un
amico ti puo' fregare sulla fiducia) e quindi so fino a dove utilizzarlo
e dove, invece, intervenire per compensarne i limiti.
Sinceramente, non ho ne' il tempo ne' la voglia (forse nemmeno la
capacita') di scrivere un mio FW attorno alle API dato che devo
dedicarmi 'anima e cuore' al dominio delle applicazioni che sviluppo.
massimo

obbligato) la via MFC e', pur con tutte le sue limitazioni, la piu'
Probabile, ma d'altra parte, se viene imposta la scelta di linguaggio, e
quella di sistema operativo da usare, e` improbabile che si lasci libera 
la scelta di framework...
Alex

 ne sono gia` fin troppe.
Non sono d'accordo. Se in Win32 sembra che ci siano troppe funzioni, è perchè
sono concepite non di rado in modo disordinato, senza una chiara
differenziazione di ambiti e di livelli e/o senza una coerenza e
complementarietà con le altre funzioni. E comunque sia quello che conta non è il
numero, ma l'ordine e la coerenza del disegno nel quale sono inserite. 
Se immaginiamo l'esistenza di una piccolo paese sperduto, dove le strade non
hanno nessun cartello che ne indica il nome, e tantomeno ci sono numeri civici,
è ragionevole supporre che per trovare un certo indirizzo ci si impieghi in
media più
tempo che non in una grande città dotata di metropolitana e di tutte le
indicazioni necessarie.

sono concepite non di rado in modo disordinato, senza una chiara
No, no, e` proprio perche` sono troppe -- come nelle API di Java,
che sopra citavi come esempio positivo.  Nessuno puo` ricordare
a memoria molte migliaia di funzioni.  Proporre di raddoppiarne il
numero per un puntiglio formale e` sconsiderato!
Alex

qualità.
Il che pone un problema interessante per il novizio/a su sistemi windows:
Che fare? Chi programma in C/C++ in questo ambiente, volente o nolente,
dovra' prima o poi scontrarsi con le MFC. 
Partendo dall'ipotesi di lavoro che le MFC non siano nel complesso un buon
esempio di libreria, cosa bisognerebbe alora consigliare ad un novizio/a? 
Io gli consigleri di partire con altro. Per me e' pericoloso iniziare con
uno strumento cosi'. Non ultimo per la complessita' del prodotto. Che poi
sul lavoro (se lavora su piattaforme windows) dovra' imparare anche le MFC
e' un altro discorso. Non si studia Dante a scuola perche' si ci aspetti di
formare tutti poeti.
Che manchi un concorrente alle MFC credo sia un problema sopratutto
psicologico. Usare la libreria del Power Build (si chiama ancora cosi'?), o
la VCL, oppure usare la MFC, perche' tanto sara' *sempre* allineata prima
degli altri sugli emmenicoli di Windows?
Credo che nella scelta di MFC molto dipenda che dal fatto che siano proposte
da Microsoft. Microsoft si puo' permettere anche di cambiare il S.O. per
venire in contro agli sviluppatori MFC, gli altri rischiano di trovarsi il
S.O. cambiato per non far funzionare bene le loro librerie.


 dunque i tuoi chiarimenti della tua posizione su questo punto.
Veramente a me non sembrava un punto di importanza cruciale, e chiarirne ogni
aspetto temo mi costringa a discorsi di una meticolosità un po' eccessiva, ma
visto che a te sembrano opportuni questi chiarimenti, eccoli:
Innanzi tutto, il mio discorso NON riguardava, e questo l'ho detto chiaramente,
la legittimità di metodi di inizializzazione che differissero l'entrata in
funzione effettiva di un oggetto. La cosa è particolarmente evidente in una
classe window, che contiene un gran numero di parametri che può
tornare utile mantenere, indipendentemente dal fatto che la window sia
attualmente esistente come oggetto Win32 (anche se poi l'impostazione di CWnd è
un'altra). 
Il bitmap, al quale il mio esempio si riferiva, è frequentemente usato come
oggetto transitorio che nasce e muore nell'ambito della stessa funzione, quindi
è già un candidato meno naturale di una window all'uso dell'inizializzazione
differita.
Tuttavia potrebbe essere usato anche come oggetto permanente, e in certi casì
può aver senso che mi riservi la possibilità di creare un'istanza di una classe
bitmap non inizializzata. Ma, in questo caso, il modo logico e lineare, e
stilisticamente corretto, per implementare un comportamento di questo genere
sarebbe (come del resto si vede in diverse altre implementazioni) l'overload del
costruttore; o al limite il solo costruttore di default, ma dei metodi con nomi
funzionalmente più appropriati come LoadFromFile LoadFromResource ecc.
Mi sembra comunque scorretto e fuorviante, in C++, chiamare un metodo "Create"
(nonostante debba rilevare che è usato anche in diversi altri framework)
per il fatto che l'oggetto, dal punto di vista del linguaggio (e della sua
logica), quando si invoca un metodo non statico, ovviamente esiste già, cioè è
già stato "creato", appunto col costruttore. La creazione effettuata dalla
funzione API CreateBitmap è qualcosa che riguarda il sistema operativo, cioè è
"creazione" solo per Windows, mentre per la classe C++ è soltanto una
inizializzazione
necessaria per il funzionamento dell'oggetto stesso, cosa che normalmente viene
fatta nel costruttore, ma, come anche tu rilevi, non necessariamente. Fin qui si
tratta di una inopportuna intrusione del livello implementativo in quello
strutturale, che introduce un'incongruenza logica. 
Se poi a questo Create si accoda il nome stesso della classe (tolto il prefisso
"C") e il nome del metodo della classe CBitmap diventa CreateBitmap, si
introduce una ridondanza che suona anche un po' ridicola (equivalente a nominare
gli attributi, ad esempio BitmapWidth, BitmapHeight ecc.), e che non fa che
inquinare la chiarezza logica del rapporto tra oggetto e suoi componenti. E
questo a causa di un'altra inopportuna intrusione (inopportuna quanto meno dal
mio punto di vista di programmatore), questa volta di un livello extra-tecnico,
ossia di presunte esigenze commerciali, che imporrebbero quella che ho chiamato
la
replica delle funzioni API, replica intesa dal punto di vista esteriore (e
quindi non riguardante altri aspetti più sostanziali che possono invece, come
dici, allontanare più che avvicinare MFC e API), consistente nel mantenimento
degli stessi nomi e degli stessi argomenti delle funzioni API nei metodi delle
classi MFC, passando sopra ad altre considerazioni relative alla logica e alla
coerenza strutturale.
Ed è soprattutto quest'aspetto che non mi piace affatto, anche perchè presuppone
che i programmatori-utenti siano delle specie di macchinette che possono fare
affidamento più sulla memoria che sul ragionamento (un pò come lo
stereotipo dello studente di scarsa intelligenza ma secchione, che riesce a
ottenere dei risultati a forza di imparare a memoria pur senza capire molto di
ciò che studia), per cui meglio fare appello alla loro capacità meccanica di
riconoscere le corrispondenze di nomi e le collocazioni spaziali (ordine degli
argomenti), che non a quella più evoluta di afferrare e introiettare un sistema
logico ben strutturato e coerente. Inoltre una tale impostazione pare un invito,
per i programmatori che vengono dal C, a mantenere il loro modo di pensare
"procedurale", piuttosto che cercare di adottare il nuovo modello a oggetti, e
un tale atteggiamento appare legittimato dall'"autorevolezza" (per me
virgolettata, ma per molti no) di un prodotto Microsoft. Quindi quella che tu
definisci una "salvaguardia degli investimenti" nella formazione, a me sembra
più un incoraggiare dei programmatori C, magari buoni, a diventare dei cattivi
programmatori C++ (che, alla lunga, NON è un buon investimento).
Se poi il termine "assurdo" ti sembra eccessivo, posso anche darti ragione, ma
francamente non mi sembra il caso, in questo contesto, di stare a misurare così
attentamente le parole, come se stessimo decidendo delle sorti di chissà cosa... 
Penso che possiamo permetterci, senza per questo dequalificare la discussione,
un maggior grado di elasticità e di badare più a cogliere il senso delle
argomentazioni nel loro insieme che ad esaminarne ogni dettaglio.
Ma, visto che hai nominato la classe CWnd, molto adatta a rappresentare la
"filosofia" MFC, ne approfitto per fare alcune considerazioni che spero ti
convincano, almeno in parte, che la mia avversione per questo framework non è
motivata da un odio viscerale nei confronti della Microsoft.
Innanzi tutto le dimensioni: più di 600 linee solo per la dichiarazione, e
questo sempre in seguito alla scelta di mettere tutti i wrapper-ricalchi delle
funzioni API. E sempre seguendo questa strada, troviamo, ad "arricchire"
l'interfaccia di CWnd, i metodi per la gestione dei timer, che assai
opportunamente sarebbero potuti essere sostituiti da una classe Timer; la serie
di metodi Get/Set con nomi complementari, tipo GetForegroundWindow e
SetForegroundWindow, ma in cui il Get è statico e restituisce un puntatore a
CWnd e il set è invece un metodo non statico, con la solita incongruenza nel
nome (che, per significare ciò che in realtà fà, avrebbe potuto essere chiamato
BringToForeground, o qualcosa del genere, mentre il Get poteva essere spostato
su una classe che inglobasse proprietà generiche dell'applicazione o del sistema
grafico - come in VCL, dove un metodo analogo compare nella classe TScreen). In
altri casi simili,
l'ambiguità è ancora maggiore, come in GetFocus e SetFocus, dove addirittura
"GetFocus" sarebbe addirittura più appropriato come nome del metodo che assegna
il focus alla window, nel senso che la window _ottiene il focus_, mentre in
realtà è un metodo statico che restituisce il puntatore alla window che ha il
focus. Ancora, troviamo una bella sequenza di 'dialog box item functions' col
wrapping nel solito modo, con l'avvertenza che "Dialog-Box Items/Controls are
not necessarily in dialog boxes!". Quindi, nessun tentativo di rimediare in
qualche modo alla confusione di windows che non sono dialogs ma possono fare da
dialogs, di oggetti che manipolano altri oggetti in vece loro, cosa già assai
discutibile in Win32, ma che con le classi diventa ancora di più un pasticcio.
Sempre a proposito di dialogs, tra i membri protetti di CWnd troviamo
addirittura... i metodi per la creazione dei Dialogs, "wrappati" due volte, qui,
e nella classe derivata CDialog. Che dire? Sarò forse troppo rigido o troppo
sensibile, ma, quando mi capita di vedere roba del genere, preferisco non
ritrovarmela sotto gli occhi una seconda volta. 
E che dire di un principiante che si trovi davanti cose simili, che insegnamenti
ne potrebbe trarre, e che spiegazioni potrebbe trovare? A me sembra probabile
che il suo cervello si affatichi inutilmente nel tentativo di trovare uno schema
logico appropriato, oppure che prenda tutto acriticamente per quello che è,
restando in uno stato di abulia intellettuale da forzata "sospensione del
giudizio".
Devo aggiungere, con un certo rammarico, che purtroppo cose del genere, con
frequenza minore e con maggiori sforzi di raggiungere una maggiore coerenza, si
trova anche in altri framework, in particolare OWL, che ha adottato la stessa
"strategia" di MFC, sia pure con un pò più di giudizio. Per questo motivo, anche
se trovo OWL nel complesso senz'altro più simile a un vero framework
object-oriented, non ne rimpiango troppo la prematura scomparsa. E auspico che
in un prossimo futuro (e Java, secondo me, fa ben sperare) si possa assistere ad
un vero rinnovamento, e si cominci davvero a programmare con metodi e strumenti
razionali, uscendo da questa fase che, sia pure attiva e vitale, mi appare come
una sorta di stadio embrionale della tecnologia dello sviluppo software.
Saluti
Paolo

"procedurale", piuttosto che cercare di adottare il nuovo modello a oggetti, e
Non c'e` nulla di intrinsecamente "procedurale" in questa impostazione;
al contrario, essa evidenzia certe caratteristiche un po' "a oggetti" delle
API di Windows.
Hmmm, messaggio troppo lungo per proseguire -- e` ora di postarlo;
finiremo in un messaggio successivo.
Alex

QUALSIASI altra cosa ECCETTO l'uso di MFC;
ci passa una bella differenza. 
Risostengo le mie posizioni.
Per me il principiante, non sa (altrimenti sarebbe un *esperto*). Per me il
principiante puo' imparare poco da un progetto come le MFC. A parte mie
considerazioni sulla qualita' del progetto MFC, mi sembra comunque poco
didattico. La sua *realta'* e' il difetto principale.
Per me il principiante deve prima di tutto farsi alcuni modelli mentali di
alcuni modi diversi di affrontare il problema. 5 modi diversi per copiare un
file, per me, sono molto piu' didattici di una funzione reale per copiare il
medesimo.
Solo DOPO che il principiante si e' fatto le ossa in mondo etereo, in cui i
problemi reali sono inesistenti, puo' nel mondo *reale*. Con qualcosa alle
spalle puo' affrontare un progetto reale.
"La soluzione giusta per me era X, ma il progettista ha scelto Y, perche'?"
E da li' partire con la rivalutazione dei propri modelli mentali, e magari
arrivare alla conclusione che essi non funzionano per nella realta' il
fattore Z, e' importante, mentre il fattore K e' tranquillamente risolto con
un metodo brutale ma efficace.
+++
Naturalmente nel *mondo reale* partire subito con le MFC puo' essere la
scelta giusta. In quel contesto specifico, con quelle condizioni al contorno
...
Ma questo e' mettere il problema sotto termini sbagliati. Il fatto che il
progetto del ponte di Messina preveda l'uso di tiranti formati da cavi
intrecciati di sezione X, non vuol dire che *normalmente* per fare un ponte
non si possa usare roba piu' *semplice*.
Per me dare le MFC ad un principiante, e come dare ad uno studente di
architettura del primo biennio il progetto del ponte di Verazzano. Troppo
presto. E questo a prescindere dalla qualita' del software delle MFC.
+++
Scusa, ma questo tuo *realismo* a tutti i costi non lo capisco. E' indubbio
che MS-Dos ha influenzato molto l'informatica. I numeri parlano per noi. Ora
tu consiglieresti ad un novizio che vuole studiare S.O. di andare sul sito
della Caldera e scaricarsi quei sorgenti? Poi magari prendersi libri per
capire il successo commerciale di quel S.O., e infine farsi una propria
analisi storica del successo del MS-Dos?
Io sono piu' Draconiano. Se ti interessi di S.o. non scaricarti l'MS-Dos.
Non partire da li'. Ci sono altre cose piu' didattiche, e piu' utili.
L'inutile (nella realta') Minix, per me, e' didatticamente piu' utile.
Poi quando il principiante non sara' piu' tale, ma non sara' ancora
diventato esperto - altrimenti poi finisce su comp.os.qualcosa e non lo
leggo piu' :-) - lo vedremo discutere sulla storia del successo del MS-Dos,
sui suoi problemi architetturali, e sui vincoli progettuali.
Ma Dopo, solo dopo.
--- (Salva il papero per le repliche) ---

 un oggetto di classe File ha un metodo isFile
Certo, messo in questo modo sembra effettivamente un'assurdità, solo che ancora
una volta è una distorsione delle mie affermazioni, il cui punto centrale decidi
di ignorare: i progettisti di MFC hanno mostrato, secondo me, di avere un
"modello di riferimento" di utente non particolarmente lusinghiero per gli
utenti stessi, non per la sciocca ragione di aver chiamato un metodo
CreateBitmap, ma perchè, preferendo una somiglianza esteriore con l'API a una
buona progettazione, hanno evidentemente ritenuto più rilevanti le capacità
mnemoniche dei programmatori che non le loro capacità logiche. 
E inoltre, come dicevo, c'è una bella differenza tra un caso sporadico come
quello di Java, (in cui peraltro generalmente è stata messa una grande cura
nella progettazione delle librerie, anche rilevando come aspetto negativo il
"ripensamento" che ha portato da AWT a Swing) e un'impostazione per certi
aspetti sistematicamente scorretta e un design generalmente trasandato come
quello di MFC.
Saluti
Paolo

> implementazioni da esaminare e studiare "come modelli"
Il problema a mio avviso e` cosa deve imparare chi una certa cosa deve
studiarla.
In merito mi sembra utile citare un articolo di C. Pescio apparso su CP
in cui parlando del corretto uso dell'ereditarieta` si faceva notare come fosse
sbagliato il classico esempio della gerarchia Persona, studente, lavoratore e
studente-lavoratore. Da una attenta lettura emergono alcuni interessanti aspetti,
in particolare viene fatto notare il perche` a livello didattico si porti un esempio
che poi e` in pratica sbagliato, ovvero l'esigenza di far notare determinati aspetti
invece di altri evitando di introdurre fonti di distrazioni.
In particolare un maggiore spirito critico avrebbe notato che le affermazioni 
dell'autore erano riferite ad un certo contesto (il C++, in cui un oggetto non puo` 
cambiare classe) e` che in particolare l'errore consiste nel non far notare che il modello 
di cui sopra presuppone (per una sua qualche eventuale validita` pratica) che o gli oggetti non debbano
mai cambiare ruolo oppure che il linguaggio permetta una tale operazione.
