If the function were virtual, then you could do this and still get the output “2”:
Parent* a = new Child();
a->say();
This works because a virtual function uses the actual type whereas a non-virtual function uses the declared type. Read up on polymorphism for a better discussion of why you’d want to do this.