PDA

Visualizza versione completa : VC++6. Parametri di CDC::SelectObject() ?


gidierre
01-06-2002, 16.48.36
Una domanda piuttosto ingenua, probabilmente, questa mia, comunque se qualcuno più esperto di me in Visual C++ potrà chiarirmi gli sarò grato.

Studiando queste righe di Visual C++ 6 :

----------------------------
1 CBrush* pOldBrush = pDC->GetCurrentBrush();
2 CBrush br;
3 br.CreateSolidBrush(RGB(255,255,0));
4 pDC->SelectObject(&br);
<....>
5 pDC->SelectObject(pOldBrush);
-----------------------------

visto che nella classe CDC SelectObject() è dichiarata come
CBrush* SelectObject( CBrush* pBrush );

1.

come mai la riga 5 ha come atteso un parametro puntatore (CBrush* pOldBrush), mentre la riga 4 ha invece un reference SelectObject(&br) ?
Capisco che
pDC->SelectObject(&br);
può sempre valere come un puntatore all'indirizzo dell'oggetto br,
mentre (*br) sarebbe certamente sbagliato e infatti non compila ,
tuttavia mi domando :

SelectObject() è stata modificata qui con overload
da SelectObject( CBrush* pBrush )
a
SelectObject( &CBrush_object)
per accettare un parametro &br invece di un CBrush* puntatore,
o no ?

Oppure, è possibile che una funzione come
void mia_funzione(puntatore);
accetti ugualmente un parametro puntatore o reference come interscambiabili senza bisogno di overload ?

2.

Ho anche notato che se scrivo invece
pDC->SelectObject(br);
cioè (br) al posto del "solito" pDC->SelectObject(&br);
al compilatore va bene lo stesso !
E dunque, questo '&br' non è poi così necessario ??
Sembrerebbe di sì, visto che SelectObject(br) funziona ugualmente.
E come fa allora a sapere di convertire (br) a (&br) ammesso che sia questo ciò che avviene qui ?

LeleB
06-06-2002, 09.15.06
----------------------------
1 CBrush* pOldBrush = pDC->GetCurrentBrush();
2 CBrush br;
3 br.CreateSolidBrush(RGB(255,255,0));
4 pDC->SelectObject(&br);
<....>
5 pDC->SelectObject(pOldBrush);
-----------------------------

visto che nella classe CDC SelectObject() è dichiarata come
CBrush* SelectObject( CBrush* pBrush );

1.

come mai la riga 5 ha come atteso un parametro puntatore (CBrush* pOldBrush), mentre la riga 4 ha invece un reference SelectObject(&br) ?
Capisco che
pDC->SelectObject(&br);
può sempre valere come un puntatore all'indirizzo dell'oggetto br,
mentre (*br) sarebbe certamente sbagliato e infatti non compila ,
tuttavia mi domando :

SelectObject() è stata modificata qui con overload
da SelectObject( CBrush* pBrush )
a
SelectObject( &CBrush_object)
per accettare un parametro &br invece di un CBrush* puntatore,
o no ?

Come tu sai, la funzione CBrush* SelectObject( CBrush* pBrush ); si aspetta che tu le passi un indirizzo e lei ti ritorna un altro indirizzo, quindi le chiamate

4 pDC->SelectObject(&br);
5 pDC->SelectObject(pOldBrush);

le passano entrambe 2 indirizzi, una recuperando l'indirizzo della variabile oggetto br e l'altra passandole il puntatore pOldBrush.


Oppure, è possibile che una funzione come
void mia_funzione(puntatore);
accetti ugualmente un parametro puntatore o reference come interscambiabili senza bisogno di overload ?

Mi sa che tu fai confusione tra puntatori e reference anche se possono sembrare simili sono molto diversi, qui stiamo parlando solo di puntatori, ad una funzione void mia_funzione(puntatore); o le passi una variabile puntatore, es. mia_funzione(Ptr);
o le passi un indirizzo (che poi è la stessa cosa in quanto un puntatore contiene un indirizzo!), es. mia_funzione(&Var);


2.

Ho anche notato che se scrivo invece
pDC->SelectObject(br);
cioè (br) al posto del "solito" pDC->SelectObject(&br);
al compilatore va bene lo stesso !
E dunque, questo '&br' non è poi così necessario ??
Sembrerebbe di sì, visto che SelectObject(br) funziona ugualmente.
E come fa allora a sapere di convertire (br) a (&br) ammesso che sia questo ciò che avviene qui ?

Funziona lo stesso in quanto br è un riferimento ad un oggetto e quindi contiene l'indirizzo di memoria che punta all'oggetto chreato.

P8257 WebMaster
06-06-2002, 11.38.47
Meenghiaaa avevo proprio perso questo thread .. :)

Complimenti a "LeleB" per la completezza e chiarezza dell'intervento.

Mi permetto di aggiungere solo una cosa, che in realtà è un consiglio: ho notato che molti utilizzano i puntatori come transizione tra routine ed oggetti a livelli diversi, personalmente consiglio (ove possibile naturalmente) di utilizzare la referenziazione diretta.

Bye :cool:

P.S.: Questo prendetelo come inciso, non è una critica ;)

LeleB
06-06-2002, 14.40.41
Sono d'accordo con te!
Per la scrittura del codice i riferimenti sono meglio dei puntatori in quanto ti permettono di passare un indirizzo come se fosse una semplice variabile, l'unica loro pecca è che a volte possono creare situazioni ambigue per quello che riguarda la comprensione dei listati.

Hola.

gidierre
07-06-2002, 02.08.18
x LeleB :

quanto al punto 1, direi che la risposta è chiarissima e l'argomento risolto, grazie.

Sul 2 però..

>> se scrivo
pDC->SelectObject(br);
cioè (br) al posto di
pDC->SelectObject(&br);
al compilatore va bene lo stesso <<

> Funziona lo stesso in quanto br è un riferimento ad un oggetto e quindi contiene l'indirizzo di memoria che punta all'oggetto creato <

più che a un "riferimento a un oggetto" come dici tu, io imho penso a un overload di
CBrush* SelectObject( CBrush* pBrush );

Infatti cercando in afxwin.h e in afxwin1.inl ho trovato che "dietro le quinte" esiste un overload di SelectObject() (se tale non è, non saprei proprio come altrimenti definirlo) anzi due.
Spero che non ti dispiaccia se li cito qui per chiarir(mi) le idee :
uno è

static CGdiObject* PASCAL SelectGdiObject(HDC hDC, HGDIOBJ h);
e accetta 2 parametri.
l'altro più interessante qui è

HGDIOBJ SelectObject(HGDIOBJ);
perciò 1 parametro, e la definizione è

_AFXWIN_INLINE HGDIOBJ CDC :: SelectObject(HGDIOBJ hObject)

{ ASSERT(m_hDC == m_hAttribDC); // ASSERT a simple CDC object

return (hObject != NULL) ? :: SelectObject(m_hDC, hObject) : NULL; }

Tu correggimi se sbaglio, ma io penso sia questo che interviene su
pDC->SelectObject(br);

In ogni caso ho provato a fare il debugging single-step usando
memDC.SelectObject(&memBitmap);
vs.
memDC.SelectObject(memBitmap);

e se ho ben interpretato tutti i messaggi,
il 1° caso è intercettato dalla versione "standard", cioè
SelectObject( CBitmap* pBitmap );

nel 2° invece quello che ho visto in azione era proprio
HGDIOBJ SelectObject(HGDIOBJ);

Quindi è giusto almeno qui parlare di overload, no ?

LeleB
07-06-2002, 11.00.32
A vedere queste routine direi proprio che hai ragione! :)

Nel mio primo post ho scritto così in quanto non conoscevo la funzione e mi sono basato solo sulla sua dichiarazione (cosa effettivamente un po' ambigua per poter dare una spiegazione)..
..avevo cercato di dare una mia interpretazione (peccando di presunzione) ma vedo che tu c'eri già arrivato!! :):)

gidierre
07-06-2002, 17.39.20
Ma che , scherzi ?
Anzi, sono io che ti sono grato per la tua "consulenza" :)

(P.S. :
Odio i reference. Ma chi **** li ha inventati ?)

P8257 WebMaster
10-06-2002, 08.52.08
Mah, a rigor di logica dovresti odiare i puntatori :confused: .. comunque, questa è un'opinione personale :D

Bye :cool: