Newsgroup: it.comp.lang.c++
Titolo: Puntatore a puntatore

class  A {
 ...
 } ;
class B : public A {
...
} ;
A **ptr ;
B *vect[2];
main()
{
 ptr = vect ;
return 0 ;
}
Il compilatore mi da errore  : " cannot convert B** to A**"
Ok non e' un A* = B*  perfettamente lecito pero' agli effetti pratici
cosa cambia ?

 ha scritto nel messaggio 
news:eccgs2l7p6mpjc03a...@4ax.com...

Il problema è che ptr e vect sono due tipi incompatibili. Mentre ptr è un 
puntatore a puntatore ad A, vect è un array di 2 puntatori a B e non ha senso 
assegnare un array ad un puntatore.
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg
The EMG Music page:         
http://www.emagsoftware.it/emgmusic
 

assegnare un array ad un puntatore.
???????????????????????
e com'e' allora che cosi funziona perfettamente ?
 class  A {
    int a ;
  } ;
 A **ptr ;
 A *vect[2];
int main(int argc, TCHAR **argv)
{
 ptr = vect ;
 return 0 ;
}
Io mi riferivo all'errore che il compilatore riporta come tipo diverso
del puntatore tra classi base e derivate .

 cosa cambia ?
Lascia perdere per un attimo gli array e considera
class C : public A {
};
int main() {
  B * pb;
  B ** ppb;
  A ** ppa;
  C c;
  ppb = &pb;  // ppb punta all'indirizzo di pb
  ppa = ppb;  // illegale: ppa punta all'indirizzo di pb
  *ppa = &c;  // pb punta all'indirizzo di c, che non e' un B!
}
Nota che l'ultima istruzione e' perfettamente legale, perche' *ppa e'
un puntatore ad A e C deriva da A.
Ciao,
Nicola

 assegnare un array ad un puntatore.
Ha perfettamente senso assegnare un array a un puntatore, se i tipi 
corrispondono.
Io un sospetto ce l'ho, ma non sono un conoscitore profondo dello 
standard (anche se mi piacerebbe).
Azzardo una spiegazione, maturata da alcune cose che ho notato in alcune 
implementazioni.
Capita che
B* x = new B();
A* y = x;
sia
(void*)x != (void*)y.
Non so se accada sempre, ma in alcuni casi DEVE essere cosi', perche' 
(immaginando il solito caso di ereditarieta' multipla diamond) A con 
figli B C, e una classe D che eredita da B e C, a seconda se la 
derivazione e' virtuale o meno, si hanno una sola copia o due copie 
distinte dell'oggetto A all'interno di D.
Nel caso di copia singola, trasformare un D* in A* e' immediato, ma se 
ci fossero due copie distinte di A, quale scegliere?
D* d = ... ;
A* a = (A*)d; // ?!?
A* a1 = (A*)((B*)d); // prima copia
A* a2 = (A*)((C*)d); // seconda copia
e' ovvio che a1 non puo' essere uguale ad a2, altrimenti punterebbero 
alla stessa copia.
A questo punto uno dei due *potrebbe* essere uguale a d, ma perche'? 
Perche' uno e' piu' bello dell'altro? E in ogni caso l'altro *dovrebbe* 
essere diverso da d.
Quindi, tornando all'esempio originale, credo che il tutto dipenda dal 
fatto che un B* e' *assegnabile* ad un A*, ma di fatto non *e'* un A*.
--
Marco

 ???????????????????????
Scusa, ho scritto una bestialità... :-(


un puntatore ad A e C deriva da A.
Non sono ancora convinto .
se  ppa = ppb fosse legale io avrei semplicemente assegnato
l'indirizzo di un  *B  a ppa .
ppa funzionerebbe correttamente perche l tipo fondamentale e' sempre
di tipo A anche se usa l'indirizzo di B .
  ppa = ppb;  // illegale: ppa punta all'indirizzo di pb
  *ppa = &c;  // pb punta all'indirizzo di c, che non e' un B!
anche qui non cambierebbe niente perche ppa e' sempre di tipo A e
anche se punta a C gli offset del puntatore all'interno di C sono
sempre corretti .
Difatti se uso una conversione esplicita da **B a **A il programma non
crasha e funziona correttamente .

 Non sono ancora convinto .
OK. Immagina che sia possibile.
 A a;
 B* bp = 0;
 B** bpp = &bp;
 A** app = bpp; // se questo fosse possibile...
 (*app) = &a;   // ... sarebbe possibile anche queso.
Però '(*app)' coincide con 'bp', e non può essere legittimo assegnare
l'indirizzo di un A a un puntatore a B.
Max
 
 

 l'indirizzo di un A a un puntatore a B.
Complimenti, veramente una bella spiegazione.
-- 
Costantino Grana 

 crasha e funziona correttamente .
Questo non significa assolutamente niente. La memoria del tuo computer
non ha tipo. Finche' stai dentro lo spazio di indirizzamento assegnato
al tuo processo e' difficile che l'esecuzione venga terminata.
Ciao,
Nicola

 al tuo processo e' difficile che l'esecuzione venga terminata.
Un esempio concreto: sul mio PC se nel programmino che segue scommento
la define ottengo un access violation.
struct A {};
static const int size = 100000000;
struct B : public A {
    char b[size];
};
struct C : public A {
    char c[5];
};
B b;
C c;
//#define ERRORE
int main() {
  B * pb;
  B ** ppb;
  A ** ppa;
  ppb = &pb;  // ppb punta all'indirizzo di pb
  ppa = (A **)ppb;  // illegale: ppa punta all'indirizzo di pb
#ifdef ERRORE
  *ppa = &c;  // pb punta all'indirizzo di c, che non e' un B!
#else
  *ppa = &b;  // pb punta all'indirizzo di b
#endif
  for ( int i = 0; i < size; ++i )
    pb->b[i] = 'b';
}
Ciao,
Nicola

#endif
Si , hai ragione 
adesso mi e' chiaro .
Grazie