I can't understand anything here. I expected that if I can pass a dog pointer to function taking animal pointer, I could also pass the &dog to a function that takes a pointer to pointer of Animal.
struct Animal{};
struct Dog : Animal{};
void ptrToPtr(Animal** arg){}
void refToPtr(Animal*& arg){}
void refToConstPtr(Animal* const & arg){}
void ptrToConstPtr(Animal* const * arg){}
int main(void)
{
Dog* dog;
Animal* animal;
ptrToPtr(&animal); // Works
ptrToPtr(&dog); // Argument of type Dog** is incompatible with argument of type Animal**
refToPtr(animal); // Works
refToPtr(dog); // A reference of type Animal*& (not const-qualified) cannot be initialized with a value of type Dog*
ptrToConstPtr(&animal); // Works
ptrToConstPtr(&dog); // Argument of type Dog** is incompatible with paramater of type Animal* const*
refToConstPtr(animal); // Works
refToConstPtr(dog); // Works. This is the only one that allows me to send Dog to Animal
return 0;
}
I just don't get it, can anyone explain what the reasons are for why particular cases work and others don't? Like passing the dog pointer address to the Animal**, that would be an upcast, wouldn't it?