In your example main() has two objects: human h1 and student s1.
int main()
{
human h1(10);
student s1(11,4);
human* p=&h1;
p->f();
p=&s1;
p->g();
}
Aside from the constructor, the declaration of the parent class human has only the function f() and the child class student, only adds the one function g().
The human pointer can look up only the function contained in it's class. Any information in the child's look up table is unknown to the parent because human was never told anything about the child class.
Passing the child object's reference &s1 to the parent pointer means that the parent can only look up the function it already knows. This is sometimes called object slicing. The child function g() has no place keeper in the parent's class. But, the child has both functions in it's look up table.
In other words, the child knows both itself and it's parent because it is declared class student: public human but the parent class knows only itself because it is merely declared "class human"
As Bauss says, it is possible to "upcast" the human pointer but I would not recommended that style. It will only confuse what type of pointer is being actually used.
This is the way I would rewrite main:
int main()
{
human h1(10);
human* p=&h1;
p->f();
/* prints " the age of human = 10" */
student s1(11,4);
student* q=&s1;
q->f();
/* prints " the age of human = 11" */
q->g();
/* prints " the student with age 10 has 4" */
}
void fand I changed that to see the effects. we have a pointer that points to a child class, why it can't find a method calledg.