PDA

View Full Version : [C++]Help getter & setter e ptr


Solido
16-05-2011, 13:58
Salve ragazzi avrei bisogno di una spiegazione un pò dettagliata su questi due metodi e vorrei capirne la sintassi!
Ho capito che servono a dichiarare e a settare il valore della variabile in questione per cui è meglio metterli nel programma...
leggo che serve anche a livello di manutebilità del codice ma qui non capisco molto...cioè alla fine non mi torna troppo dove sta il risparmio di tempo!
C'entra qlcs il puntatore this?
quest'ultimo come funziona?
grazie mille :stordita:

GByTe87
16-05-2011, 16:04
Get/Set si usano per avere accesso alle variabili membro di un oggetto, nel caso in cui queste siano state dichiarate "private".

Il nascondere l'accesso alle variabili membro è uno dei metodi con cui realizzato l'incapsulamento. Non si tratta di un metodo per risparmiare tempo. :)

Non capisco un riferimento al puntatore this, esso non è altro che un riferimento all'oggetto che ha generato la chaimata. :D

Solido
16-05-2011, 16:11
Perché mi pareva che nel set ci foss sempre un this ->

Naufr4g0
16-05-2011, 20:06
Perché mi pareva che nel set ci foss sempre un this ->

beh si si mette quando vuoi utilizzare come parametro della funzione lo stesso nome della variabile membro dell'oggetto, tipo:


void MyClass::SetVar (int var)
{
this->var = var;
}


In questo modo fai capire al compilatore che si tratta di due var diversi.
Io in genere però metto nomi diversi ed evito il problema:


void MyClass::SetVar (int var)
{
mVar = var;
}

Solido
18-05-2011, 10:09
beh si si mette quando vuoi utilizzare come parametro della funzione lo stesso nome della variabile membro dell'oggetto, tipo:


void MyClass::SetVar (int var)
{
this->var = var;
}


In questo modo fai capire al compilatore che si tratta di due var diversi.
Io in genere però metto nomi diversi ed evito il problema:


void MyClass::SetVar (int var)
{
mVar = var;
}



ecco appunto basta cambiare nome!!! ma quel mVar non deve essere dichiarata all'interno di MyClass?

ecco ora ho un dubbio sui costruttori... perchè leggendo i vari libri si perdono in mille esempi ma non mi riesce di capirne la sintassi:
il distruttore basta mettere un ~nomedellaclasse
per i costruttori invece? perchè alle volte vedo i :: alle volte no
:help:

GByTe87
18-05-2011, 11:32
ecco appunto basta cambiare nome!!! ma quel mVar non deve essere dichiarata all'interno di MyClass?

mVar deve essere una variabile membro di MyClass.

ecco ora ho un dubbio sui costruttori... perchè leggendo i vari libri si perdono in mille esempi ma non mi riesce di capirne la sintassi:
il distruttore basta mettere un ~nomedellaclasse
per i costruttori invece? perchè alle volte vedo i :: alle volte no
:help:

Se dichiari e implementi una funzione (inclusi costruttori e distruttori, quindi) contestualmente, durante la definizione della classe non c'è necessità di utilizzare l'operatore di scope resolution (ossia il :: ). Attenzione che così facendo le funzioni vengono automaticamente dichiate inline.

Se, invece, dichiari una funzione all'interno della classe e la definisci fuori dalla classe, il compilatore necessita di sapere che la funzione che stai scrivendo si riferisce a quella classe.
Cosa che fai usando la notazione NomeClasse::NomeFunzione().

Data una classe MyClass, comunque, il costruttore (o i costruttori) si chiameranno sempre MyClass, mentre il distruttore ~MyClass.

Solido
18-05-2011, 12:56
mVar deve essere una variabile membro di MyClass.



Se dichiari e implementi una funzione (inclusi costruttori e distruttori, quindi) contestualmente, durante la definizione della classe non c'è necessità di utilizzare l'operatore di scope resolution (ossia il :: ). Attenzione che così facendo le funzioni vengono automaticamente dichiate inline.

Se, invece, dichiari una funzione all'interno della classe e la definisci fuori dalla classe, il compilatore necessita di sapere che la funzione che stai scrivendo si riferisce a quella classe.
Cosa che fai usando la notazione NomeClasse::NomeFunzione().

Data una classe MyClass, comunque, il costruttore (o i costruttori) si chiameranno sempre MyClass, mentre il distruttore ~MyClass.


ok quindi i :: funzionano anche per i costruttori?

se ad es ho una classe stack così definita:

class stack{
protected:
int tos;
data*buffer;
int size;

public:
stack(int s);
stack( int s, data v);
~stack(void)
boolean push( data value );
boolean pop ( data* value_ptr);
};

stack:: stack ( int s ) : tos(0), size (s), buffer( new data[s])
{}

ho che il costruttore si riferisce a stack e ne inizializza i dati membro protetti?
e quell' int s in parensi ?

GByTe87
18-05-2011, 13:11
Si, quello è il costruttore; (int s) indica i parametri da passare al costruttore, in questo caso un intero.

Se ci fai caso, lo stesso intero, (la variabile s) viene passato ai costruttori degli oggetti/variabili membro della classe.

Ti consiglierei, se vuoi darti al C++, di partire con un buon libro; apprendere nozioni in questo modo, mano a mano che incontri cose che non conosci, non è il massimo; rischi di ritrovarti grosse lacune più avanti. ;)

Solido
18-05-2011, 14:07
Si, quello è il costruttore; (int s) indica i parametri da passare al costruttore, in questo caso un intero.

Se ci fai caso, lo stesso intero, (la variabile s) viene passato ai costruttori degli oggetti/variabili membro della classe.

Ti consiglierei, se vuoi darti al C++, di partire con un buon libro; apprendere nozioni in questo modo, mano a mano che incontri cose che non conosci, non è il massimo; rischi di ritrovarti grosse lacune più avanti. ;)

ma infatti ho dei libri solo che queste sono le cose che nn sono spiegate ,imho, bene! Gli approcci troppo pratici lasciano delle lacune!

cmq quel valore int s vuol dire che richiama il primo costruttore che accetta solo un paramentro?

Naufr4g0
19-05-2011, 10:30
Ma invece di partire da queste complesse strutture dati non è meglio fare cose più semplici senza puntatori magari?
Si rischia di impazzire se si comincia così!
Se ti servono strutture dati usa le STL: vector, list, ...

Tornando al discorso dei " :: "

Si usano quando definisce un metodo non in line, cioè fuori dalla dichiarazione della classe

inline:

class MyClass {
....
void SetVar (int var) { mVar = var; }
....
}


alternativa:

class MyClass
{
void SetVal(int val);
}

MyClass::SetVal(int val)
{
mVar = var;
}


Se la scrivi così


inline MyClass::SetVal(int val)
{
mVar = var;
}


è come se l'avessi scritta dentro la definizione della classe come nel primo caso.

Solido
19-05-2011, 19:20
Beh ho messo quell'esempio perchè stavamo trattando argomenti del genere e non perchè mi voglio complicare la vita :p
cmq grazie mi sei stato piuttosto di aiuto!

però non capisco bene il 3° esempio...
ho visto che inline è una parola chiave, quindi io in quel modo avverto il compilatore della dichiarazione in line. Ma la parola class?
cioè quelle istruzioni seguono la dichiarazione della classe:


class MyClass {
....
void SetVar (int var) { mVar = var; }
....
}

oppure no?

grazie mille

Naufr4g0
19-05-2011, 22:27
Quindi mi spiego, o fai come nel primo caso


class MyClass {
....
void SetVar (int var) { mVar = var; }
....
}


e il metodo è già dichiarato implicitamente inline, oppure scrivi solo il prototipo del metodo


void SetVar (int var);


all'interno della definizione della classe e lo implementi all'esterno


inline MyClass::SetVal(int val)
{
mVar = var;
}


ed hai ottenuto due cose equivalenti.
Il motivo per cui c'è questa seconda alternativa è solo per la pulizia del codice. :)
In genere i prototipi si mettono in un file header (.h) con la definizione della classe, mentre le implementazioni (inline o no che siano) in un file .cpp con lo stesso nome dell'header.

Solido
21-05-2011, 15:36
quindi se ho capito...

nel primo caso definisco il metodoSetVar all'interno della classe e questo mi fa una assegnazione: prendo il parametro di input e lo assegna a mVar
mentre nel secondo caso io dichiaro il prototipo in un header file e lo definisco all'esterno e poi quando lo vorrò utilizzare , ad es nel main, dovrò scrivere:
SetVal( int 5) ad es?
perchè VaL e non VaR?

grazie in anticipo


poi per es ci sono anche questi es con questa sintassi qua:
imageTemplate(int w, int h) : _w(w), _h(h){ _pixels= new T[_w*_h];};
nella tonda ci sono i paramenti che passo a imageTemplate nella graffa c'è la definizione del costruttore mentre " :_w(w), _h(h)" cos'è?

edit: dubbio ulteriore:
tornando all'esempio dello stack che ho fatto ad inizio pagina:
se per dire dopo ho una funzione così:
void client(void)
{
stack S;
stack S2(10);
stack S3(10,20);
...o anche una assegnazione del tipo
sptr= new stack(10,5);
}

in questo caso il compilatore mi dovrebbe automaticamente richiamare il costruttore giusto no?
ma quei nomi: S, S2 ecc... non vanno dichiarati prima?

GByTe87
21-05-2011, 18:12
quindi se ho capito...

nel primo caso definisco il metodoSetVar all'interno della classe e questo mi fa una assegnazione: prendo il parametro di input e lo assegna a mVar
mentre nel secondo caso io dichiaro il prototipo in un header file e lo definisco all'esterno e poi quando lo vorrò utilizzare , ad es nel main, dovrò scrivere:
SetVal( int 5) ad es?

nomeOggetto.SetVal(5);

perchè VaL e non VaR?

Alle funzioni normali (non costruttori e distruttori) puoi dare il nome che preferisci, quindi non c'è differenza.


poi per es ci sono anche questi es con questa sintassi qua:
imageTemplate(int w, int h) : _w(w), _h(h){ _pixels= new T[_w*_h];};
nella tonda ci sono i paramenti che passo a imageTemplate nella graffa c'è la definizione del costruttore mentre " :_w(w), _h(h)" cos'è?

In questo caso il costruttore di una classe derivata passa dei parametri ai costruttori delle classi da cui deriva. (Molto probabilmente _w e _h sono dei membri della tua classe).

edit: dubbio ulteriore:
tornando all'esempio dello stack che ho fatto ad inizio pagina:
se per dire dopo ho una funzione così:
void client(void)
{
stack S;
stack S2(10);
stack S3(10,20);
...o anche una assegnazione del tipo
sptr= new stack(10,5);
}

in questo caso il compilatore mi dovrebbe automaticamente richiamare il costruttore giusto no?

Si, il compilatore riconosce il costruttore corretto e lo invoca. (l'overload funziona senza problemi anche per i costruttori).

ma quei nomi: S, S2 ecc... non vanno dichiarati prima?

E perchè mai? Sono i nomi delle istanze della classe stack.
La stessa cosa che fai con "int i;", per intenderci.

Solido
21-05-2011, 18:37
nomeOggetto.SetVal(5);

OK




Si, il compilatore riconosce il costruttore corretto e lo invoca. (l'overload funziona senza problemi anche per i costruttori).


Ok



E perchè mai? Sono i nomi delle istanze della classe stack.
La stessa cosa che fai con "int i;", per intenderci.

Questi punti ora mi sono chiari, mentre non mi sono chiari gli altri 2:

"Alle funzioni normali (non costruttori e distruttori) puoi dare il nome che preferisci, quindi non c'è differenza."

non capisco come possa scrivere un certo nome nel prototipo e poi utilizzare un altro nome per definire la funzione:

void SetVar (int var);



inline MyClass::SetVal(int val)
{
mVar = var;
}


come fa il compilatore a collegare SetVal e SetVar?


"In questo caso il costruttore di una classe derivata passa dei parametri ai costruttori delle classi da cui deriva. (Molto probabilmente _w e _h sono dei membri della tua classe)."

Che diff c'è allora tra i paramentri _w,_h e quello passato nella parentesi tonda:
imageTemplate(int w, int h) ?

grazie mille per adesso:
ps: che libri hai usato per studiare?
perchè io ho quello di Stroustrup in persona ma non riesce a fugarmi questi dubbi :(

GByTe87
21-05-2011, 18:43
"Alle funzioni normali (non costruttori e distruttori) puoi dare il nome che preferisci, quindi non c'è differenza."

non capisco come possa scrivere un certo nome nel prototipo e poi utilizzare un altro nome per definire la funzione:

void SetVar (int var);



inline MyClass::SetVal(int val)
{
mVar = var;
}


come fa il compilatore a collegare SetVal e SetVar?

Sorry, mi ero perso un pezzo. Il nome della funzione nel prototipo e nell'implementazione devono essere uguali. Quindi si, dev'essere SetVar.

"In questo caso il costruttore di una classe derivata passa dei parametri ai costruttori delle classi da cui deriva. (Molto probabilmente _w e _h sono dei membri della tua classe)."

Che diff c'è allora tra i paramentri _w,_h e quello passato nella parentesi tonda:
imageTemplate(int w, int h) ?

Nella parentesi tonda hai i parametri passati dal chiamante, mentre _w e _h saranno le variabili membro della tua classe.


grazie mille per adesso:
ps: che libri hai usato per studiare?
perchè io ho quello di Stroustrup in persona ma non riesce a fugarmi questi dubbi :(

Diciamo che sto approdando al C++ in questo periodo dopo 3 anni di C puro.
Sto usando come libro "C++: The Complete Reference" di Schildt. :)