Newsgroup: it.comp.programmare.win32
Titolo: [MFC] Passaggio di istanze

Buonasera a tutti,
ho un comportamento in una classe C++ derivata da CObList che mi risulta
abbastanza strano.
Gli oggetti della lista sono omogenei e derivati direttamente da
CObject. La lista viene riempita leggendo da un file. Ho questi metodi
per farmi restituire oggetti dalla lista che non funzionano: ovvero,
trovano correttamente l'elemento cercato, tornano true, ma nel chiamante
il parametro attuale ha valore NULL.
Cosa e' che non vedo / non so?
bool GetPresaByID(TID anID, CPresa *dest);
...
bool CListaPrese::GetPresaByID(TID anID, CPresa* dest)
{
 for (POSITION pos = GetHeadPosition(); pos != NULL; ) {
  dest = (CPresa*)GetNext(pos);
  if ((dest->Detail() != sdFree) && (dest->fID == anID))
   return true;
 }
 dest = NULL;
 return false;
}
// chiamante: al ritorno da GetPresaByID p e' NULL anche nel ramo true
 CPresa* p;
 CString strPresa;
 char buffer[132];
 p = NULL;
 strPresa.Format(_T("Numero prese Off: %d\r\n"), pLista->NumPreseOFF());
 m_EditText += strPresa;
 for (int i = 0; i < pLista->NumPrese(); i++) {
  if (pLista->GetPresaByID(i+1, p)) {
   p->ToString(buffer);    // <<< Access violation
   strPresa.Format(_T("Presa %d: %S\r\n"), i, buffer);
  }
  else
   strPresa.Format(_T("Presa non valida all'indice %d\r\n"), i);
  m_EditText += strPresa;
 }
 UpdateData(false);
Grazie in anticipo e
Saluti
Paolo Arosio

 }
La funzione modifica il parametro dest, ma le modifiche vengono 
effettuate su una copia del puntatore passato in ingresso, che rimane 
quindi immutato nella funzione chiamante.
Per ovviare al problema dovresti passarlo come reference (&) o come 
puntatore a un puntatore.
-- 
Valter Minute
vmi...@inwind.it
 (the reply address of this message is invalid)

 puntatore a un puntatore.
Al problema ho rimediato restituendo il puntatore all' istanza trovata
invece di passarlo come parametro [ if ((p = GetByID(anID)) != NULL) ],
pero' mi (vi) chiedo se e' standard del C++ di considerare const un
puntatore passato come parametro (o e' cosi' anche in C)?
Saluti
Paolo Arosio

 
Effettivamente ritornare il puntatore modificato è meglio che 
passarlo come parametro, non avevo considerato che la tua funzione è 
void.
Il C++ non lo considera const, se così fosse non te lo lascerebbe 
modificare!
I parametri (in C e in C++) vengono passati per valore (copiati nello 
stack). 
Sono modificabili all'interno della funzione ma, una volta che questa 
ritorna al chiamante, le copie vengono distrutte. 
In C non esisteva il passaggio  per reference e quindi o si passavano 
puntatori (puntatori a puntatori, nel tuo caso).
Questo implica che passare come parametro (senza puntatore) delle 
strutture o delle classi con parecchi datamembers è sconsigliabile 
perchè genera delle copie di dati che rallentano la chiamata a 
funzione (fatto salvo, ovviamente, il caso in cui la copia deve 
essere modificata senza che le modifiche vengano riportate al 
chiamante).


puntatore passato come parametro (o e' cosi' anche in C)?
No.
Un puntatore non č soggetto a regole diverse rispetto a tutti gli
altri tipi, nel passaggio a funzioni.  Se viene passato come
non-const, lo puoi modificare, ma č chiaro che le modifiche sono
valide solo in locale, nella funzione.  Se vuoi renderle permanenti,
devi passarlo per riferimento.  In C++ il passaggio per riferimento
sfrutta i reference, in C il passaggio mediante puntatore:
// passaggio per valore:
procedure Pippo(P: Pointer); // Delphi
void pippo(void *p); // C/C++
// passaggio per riferimento:
procedure Pippo(var P: Pointer); // Delphi
void pippo(void **p); // C
void pippo(void* &p); // C++
-- 
Andrea Laforgia - a.laforgia(at)
libero.it
"There are three kinds of people in this world; 
 those who are good at maths and those who aren't".

 stack).
Quindi a GetByID e' stata passata una copia di p.
Per fare quel che desideravo avrei quindi dovuto dichiarare
GetByID(int anID, CItem** dest);
e chiamarlo con
if (GetByID(100, &p))
  p->Aziona();
Ma all'interno del GetById, una volta che ho il riferimento all'oggetto
cercato, come lo assegno al parametro? Con
  *dest = (CItem *)GetHead();    // supponendo ci sia l'elemento cercato
  return (*dest != NULL);
/ me si confonde gia' al secondo livello di indirezione
Saluti
Paolo Arosio

  *dest = (CItem *)GetHead();    // supponendo ci sia l'elemento cercato
Esatto.
Esempio:
void alternativa1(void **p, size_t s)
{
     *p = malloc(s);
}
void* alternativa2(size_t s)
{
     return malloc(s);


 }
...
A volte vale piu' una riga di codice che 20-100 parole...
Grazie per l'aiuto -anche a Valter Minute- e (btw) bentornato su icld.
Saluti
Paolo Arosio