you created an array of three penguins, then you reinterpreted it as an array of birds.
array1 points to the beginning of the first element of the array, and pretends that it's a bird, so birds's member function print reads the first member variable in the object ( that's 1 ) and prints that
array1 takes the pointer to the first penguin and increments it by the size of bird, and then it interprets the bytes it finds there as a bird. It so happened in your case that it hit exactly the second member variable (speed) or the FIRST penguin. Bird's function print, thinking it's reading age, read the bytes that constitute the first penguin's speed and printed them as age
array increments the pointer by two bird sizes, which happens to hit exactly the beginning of your Second penguin, so it prints the second penguin's age
when i write Bird *array1 = new peng[size];. This means that array will store pointer to Bird objet.
No, this means the nameless array created by new will store three whole penguin objects, no pointers are stored in it (an array of size pointers to penguins could be created with new peng*[size];). And then it stores the address of the first element of the array in the pointer object "array1", which happens to have the wrong type.