Newsgroup: it.comp.lang.c++
Titolo: Accedere ai membri

Sono un ex-programmatore Pascal, e come tale trovavo molto comoda la
possibilità di evitare di inserire ogni volta che accedevo ai membri di un
oggetto il nome della variabile base, con l'istruzione WITH.
Esempio:
    with NomeDelRecord do
    begin
        Membro1 := 4;
        Membro2 := 4;
        Membro3 := 4;
    end;
C'è la possibilità di fare qualcosa del genere anche in C++?
--
Kojak
vrke...@hotmail.com
http://space.tin.it/io/viscorci

 C'è la possibilità di fare qualcosa del genere anche in C++?
No, però in linea teorica non dovresti mai accedere alle variabili di una
classe da fuori, ma sempre utilizzare funzioni membro, le quali per
l'appunto accedono agli elementi direttamente (sottintendono this->).
Questa è sola teoria ovviamente ....
-----
Giovanni Bajo
Lead Programmer
Prograph Research S.r.l.
http://www.prograph.it

Ciao Luca, beh, in realtà non dovresti accedere alle variabili membro di una
classe, forse anche per questo non è previsto questo metodo d'accesso,
infatti, le variabili di una classe dovrebbero essere proprietà esclusiva
della classe, forse ti chiederai?, allora come faccio ad esportare le
variabili nel casono me ne serva il valore, in genere è buona tecnica fare
tutti i dati una classe private e poi scrivere dei metodi magari inline, che
restituiscono e settano il contenuto delle variabili!

In C++ non esiste un diretto corrispondente dell'istruzione WITH, anche
perche' potendo compiere cicli usando puntatori o iteratori come
variabili di controllo, il problema e' molto meno sentito.
Ad esempio (scritto di getto e non compilato):
struct LaMiaStruttura {
  int a;
  int b;
  int c;
};
LaMiaStruttura[5] arrayDiMieStrutture;
int main(int argc,char ** argv) {
  for ( LaMiaStruttura * p = arrayDiMieStrutture; 
        p < arrayDiMieStrutture + 5; ++p )
  {
     p->a = 1;
     p->b = 2;
     p->c = 3;
  }
}
Ciao,
Nicola
P.S. In generale e' meglio non sparare messaggi a raffica su molti
gruppi, ma scegliere quello piu' adatto alla propria richiesta.

 C'è la possibilità di fare qualcosa del genere anche in C++?
Purtroppo no -- il "with", che trovavo anch'io molto comodo, sembra
fuori moda nei linguaggi moderni.
Vero e` che, al giorno d'oggi, il "record" sarebbe probabilmente una
classe, con un qualche metodo SetMembri da chiamare tipo
    NomeDelRecord.SetMembri(4,4,4);
per cui la comodita` del "with" diminuirebbe.  Tuttavia, a volte ci
si trova a lavorare con strutture PODS (particolarmente, ad esempio,
nella programmazione a livello di API in Win32), e li` si "soffre".
Una utile _abbreviazione_ si puo` comunque fare con i reference:
    {
        TipoRecord& r(NomeRecordMoltoLungoCheNonVoglioRipetere3Volte);
        r.Membro1 = r.Membro2 = r.Membro3 = 4;
    }
Qualunque compilatore degno di questo nome non ti fara` pagare
nessun prezzo a run-time per l'uso di questo tipo di scorciatoie.
Alex

C'è la possibilità di fare qualcosa del genere anche in C++?
Non lo so,ma comunque non mi sembra un buono stile di programmazione
ad oggetti. L'ideale é sempre quello di creare dei dati membro privati
ed accedervi tramite le funzioni membro pubbliche.O magari utilizzare
delle funzioni friend.
Il Ghenio

Grazie a tutti per le risposte, ma avrei bisogno di qualche ulteriore
delucidazione.
Ho capito che dichiarare i membri come private ed utilizzare funzioni per
accedervi è molto più corretto, ed in effetti in alcuni casi decisamente
utile (mi riferisco ad esempio, con MFC, alla necessità di modificare alcuni
valori di un CDocument e sucessivamente chiamare il membro SetModifiedFlag),
ma in effetti non mi sono spiegato bene, eccovi dettagliatamente il mio
caso.
// CBilancioDialog deriva da CDialog
CBilancioDialog BilancioDialog;
BilancioDialog.Budget = pDocument->GetBudget();
BilancioDialog.Totale = pDocument->GetTotale();
BilancioDialog.Create([...]);
[...una serie di calcoli ...]
BilancioDialog.DestroyWindow();
Volevo sapere se c'è un modo per evitare di ripetere BilancioDialog.
Grazie alle vostre risposte ho capito che ciò non è possibile (sigh!), ma
adesso ho delle altre curiosità: in una delle risposte (Il Ghenio) si parla
di funzioni friend. In breve, qualcuno può spiegarmi cosa significa?
Idem per le funzioni inline... (Asm) ho visto da altri sorgenti che sono
funzioni dichiarate ed implementate all'interno dei file .h, ma cosa cambia?
Un'ultima cosa: ho lavorato per un mese circa con il Borland C++ Builder e
lì ho scoperto che c'è la possibilità di inserire direttamente nella
dichiarazione il membro che andrà chiamato per accedere alla variabile, se
non ricordo male qualcosa del tipo
    int membro(read=membro; write=SetMembro);
Ok, non mi ricordo se la scrittura fosse proprio questa, ma la sostanza è la
stessa: in questo modo potevo accedere alla variabile normalmente in
lettura, e la funzione SetMembro veniva chiamata automaticamente in
scrittura.
E' possibile farlo in Visual C++?
Grazie a tutti


E' possibile farlo in Visual C++?
Si trattava di "property" esclusivo di Borland, non conosco equivalente in
Visual c++
Lorenzo

 BilancioDialog.DestroyWindow();
Se la funzione è così breve, potresti, senza perdere in leggibilità, usare
un nome più breve.
CBilancioDialog d;
d.Budget = pDocument->GetBudget();
d.Totale = pDocument->GetTotale();
d.Create([...]);
[...una serie di calcoli ...]    // Meglio magari in una funzione separata
d.DestroyWindow();
Ciao
--
Alessandro Monti

Ciao Luca, beh visto che ti interessa l'argomento, un funzione inline non e'
esattamente una funzione definita in un .h, pero' una funzione definita in
un .h e' in genere una funzione inline, in pratica se una funzione e'
inline, durante la compilazione tutte le chiamate a quella funzione vengono
risolte con la sostituzione del codice della funzione stessa, anziche con la
chiamata alla funzione, questa tecnica incrementa notevolmente le
prestazioni, ma conviene usarla solamente per funzioni moolto piccole (con
poco codice), ad esempio per i metodi che settano o restituiscono il valore
dei membri interni della classe, se le funzioni che dichiari inline non sono
piccole rischi di ingigantire notevolmente il codice, tuttavia devi
ricordare che il compilatore puo' benissimo decidere di non trattare come
inline un metodo che avevi specificato inline, i motivi dipendono dal
compilatore stesso (ad esempio se ci sono dei cicli nidificati nella
funzione), i metodi che vengono dichiarati e definiti all'interno della
dichiarazione della classe stessa vengono trattati automaticamente come
inline senza specificarlo.
Per dichiarare un metodo inline devi specificare la parola inline prima
della dichiarazione del metodo e prima della sua definizione in questo modo:
class Prova    {
    Prova();
    inline void EccoLaFunzioneInline();
}
Prova::Prova()
{
}
 inline void EccoLaFunzioneInline()
{
}
Spero di essere stato chiaro (forse non troppo)!!
Byez

 E' possibile farlo in Visual C++?
Si` (vedi __declspec(property); almeno, Microsoft, nelle sue estensioni,
rispetta lo standard C++, mentre Borland qui lo viola), ma non lo fare; e`
una pessima idea di Borland, e il fatto che la implementi anche Microsoft
non la migliora affatto.  Ti pone fuori dallo standard, senza altri vantaggi
che un modesto zucchero sintattico, e ti potra` impedire in futuro di usare
altri ottimi compilatori, piu` standard, come gcc, kcc, Comeau, eccetera.
Sospetto che la stessa persona (il chief architect [o simile] della Borland,
che passo` poi alla Microsoft per mucho $$$) sia responsabile di entrambe
le estensioni (con egual semantica benche` sintassi diversa), perche`
questa delle "funzioni implicitamente chiamate quando xyz" e` una sua
vecchia mania. (Un'altra e` quella dei "bound method", che questo
individuo ficco` nell'Object Pascal di Delphi e poi piu` tardi nel Java
della MS con lo strano nome di "delegate", ma questa e` un'altra storia
e per fortuna non tocca [ancora?-)] il C++...).  (Il buffo e` che, a parte
le manie relative alle estensioni ai linguaggi, e` un _ottimo_ architetto
di framework e librerie -- VCL di Borland, e WFC di MS, entrambe a lui
dovute, sono assai usabili -- mah...!-).
Alex

 Alex
Il fatto e' che questi meccanismi sono indispensabili per implementare
il paradigma di component based programming che sta alla base di
strumenti RAD come Delphi/C++Builder (ma anche i Java Beans, e da un
certo punto di vista persino Xt), per linguaggi che non implementano un
vero e proprio meccanismo di riflessione come quello di Java.
Avendo dovuto implementare un meccanismo di persistenza generico per il
C++, basato su RDBMS, ne ho sentito decisamente la mancanza, ed ho
dovuto ricorrere pesantemente alla generazione di codice (source code
based reflection? :-)
Ciao,
Nicola

Benissimo ragazzi, grazie a tutti per le esaurienti spiegazioni!
Un'altra domanda, forse più facile: qualcuno sa dove trovare un tutorial che
spieghi cosa sono le funzioni friend?


Ottima spiegazione, grazie mille!
Provvedo subito a convertire i miei metodi piů piccoli!


Oops! Scusate, non mi ero accorto che qualcuno mi avesse già risposto!


 strumenti RAD come Delphi/C++Builder (ma anche i Java Beans, e da un
Indispensabili, non mi pare: definire interfacce corrispondenti, e
sancire che se un componente supporta la funzionalita` X lo fa
implementando l'interfaccia Y mi sembra un ottimo modo di
implementare il component-based programming -- e` quello che
fa il COM, e se anche i Java Beans hanno fatto anche uso della
reflection, comunque implementare interfacce resta la strada
maestra.  Ovviamente occorre un modo di chiedere se una data
interfaccia e` implementata (QueryInterface in COM, il
dynamic_cast in C++, il semplice cast in Java).
Alex

 
Per poter usare i componenti all'interno di un IDE che ne consenta la
configurazione con strumenti visuali e non solo da codice e'
indispensabile che l'IDE possa conoscere in modo esplicito, e attraverso
un meccanismo generico, i parametri configurabili di ciascun componente.
Xt lo fa' tramite convenzioni di codifica (anche perche' in C), Java
attraverso convenzioni di codifica e la reflection, C++Builder/Delphi
tramite properties e altro.
Che poi la scelta di Borland sia opinabile, concordo, ma anche senza
l'esigenza di agganciare le VCL e quindi l'Object Pascal, non credo ci
fossero alternative ad estendere il linguaggio.
Ciao,
Nicola