Reputation: 43
I have a problem in understanding one important aspect of the c++. see the example below:
class human
{
protected:
int age;
public:
human(int a){age=a;}
void f(){cout<<"\n the age of human ="<<age;}
};
and the class below is derived from above class:
class student: public human
{
private:
int num;
public:
student(int b, int c):human(b){num=c;}
void g(){cout<<"\n the student with age "<<age<<" has " <<num;}
};
now I want to use these classes in the code below:
int main()
{
human h1(10);
student s1(11,4);
human* p=&h1;
p->f();
p=&s1;
p->g();
}
but the compiler gives me error on the p->g()
.
what is the problem?
Upvotes: 0
Views: 1903
Reputation: 21
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" */
}
Upvotes: 0
Reputation: 329
You can announce a virtual g in the Human.
class human {
public:
virtual void g() {}
... ...
};
Upvotes: 0
Reputation:
Your base class pointer still points to a base class object human* p=&h1;
. Try something like this:
#include <iostream>
class human
{
protected:
int age;
public:
human(int a){ age = a; }
void f(){ std::cout << "\n the age of human =" << age; }
virtual void g(){}
};
// class student code here...
int main()
{
human* p = new student(11, 4);
p->f();
p->g();
delete p;
return 0;
}
or instead use the s1
object and not the h1
:
student s1(11, 4);
human* p = &s1;
Upvotes: 1
Reputation: 2797
The compiler doesn't know that your pointer is of student
, it only sees the declaration as human
. To fix this you need to cast it to a student pointer.
((student*)p)->g();
Upvotes: 0
Reputation: 16086
The function g()
is not part of the interface of the class human
. p
is a human*
. If you upcast p
to a student*
, it will work.
Upvotes: 0