Polimorfismo e puntatori agli array

Ho una class A:

class A { public: virtual double getValue() = 0; } 

E una class B:

 class B : public A { public: virtual double getValue() { return 0.0; } } 

E poi in main () lo faccio:

 A * var; var = new B[100]; std::cout << var[0].getValue(); //This works fine std::cout << var[1].getValue(); //This, or any other index besides 0, causes the program to quit 

Se invece lo faccio:

 B * var; var = new B[100]; std::cout << var[0].getValue(); //This works fine std::cout << var[1].getValue(); //Everything else works fine too 

Tutto va bene, ma sembra che ci sia qualcosa di sbagliato nel mio polimorfismo, forse? Sono perplesso.

Non è ansible trattare gli array in modo polimorfico, quindi mentre il new B[100] crea un array di oggetti B e restituisce un puntatore all’array – o equivalentemente il primo elemento dell’array – e mentre è valido assegnare questo puntatore a un puntatore a una class base, non è valido per trattare questo come un puntatore in una matrice di oggetti A

Il motivo principale per cui non è ansible è che gli oggetti derivati ​​(tipicamente) hanno una dimensione diversa rispetto alle loro classi base, quindi il tentativo di accedere all’array come una matrice di oggetti class base non utilizzerà l’offset corretto per ottenere un puntatore al successivo subobject di class base del prossimo membro dell’array di class derivato.

Non c’è alcun problema con il polimorfismo ma con il modo in cui si ha a che fare con la memoria. L’operatore [] ti farà avanzare attraverso l’array di sizeof (A) byte nel primo caso e sizeof (B) byte nel secondo caso. Poiché gli oggetti sono di tipo B, A * non punta alla posizione corretta in memoria.

Ecco un altro modo di guardarlo

 char * var; var = (char*) new B[100]; std::cout << ((A*)var[0]).getValue(); //This works fine std::cout << ((A*)var[1]).getValue(); //This will fail std::cout << ((A*)var[sizeof(B)]).getValue(); // should work 

Non hai allocato gli oggetti nell’array:

 for (int i=0;i<100;i++) var[i] = new B; 

(anche se potrei mescolare C ++ e C #)