一、子类对象可以当做父类对象使用(兼容性)
1、子类对象可以直接赋值给父类对象
2、子类对象可以直接初始化父类对象
3、父类指针可以直接指向子类对象
4、父类引用可以直接引用子类对象
5、当父类指针(引用)指向子类对象时:
(1)、子类对象退化为父类对象
(2)、只能访问父类中定义的成员
(3)、可以直接访问被子类覆盖的成员
#include<iostream> using namespace std; class Parent { public: int mi; void add(int v) { mi += v; } }; class Child : public Parent { public: int mv; void add(int x, int y) { mv = (x + y); } }; int main() { Child c; Parent p(c);//子类对象可以直接初始化父类对象 Parent p1; p1 = c;//子类对象可以直接赋值给父类对象 Parent &rp = c; Parent *pp = &c;//父类对象的指针(引用)指向子类对象,使其退化为父类对象 rp.mi = 100; rp.add(1);//可以直接访问被子类覆盖的成员 cout << pp->mi << endl;//101 // pp->mv = 1000;//已退化成父类对象,只能访问父类对象中的成员 // pp->add(100, 1); return 0; }
二、函数重写与赋值兼容
1、函数重写
(1)、子类中可以定义父类中已经存在的成员函数
(2)、这种重定义发生在继承中,叫做函数重写
(3)、函数重写是同名覆盖的一种特殊情况
2、当函数重载遇上赋值兼容
(1)、编译期间,编译器只能根据指针的类型判断所指向的对象
(2)、根据赋值兼容,编译器认为父类指针指向的是父类对象
(3)、因此,编译结果只能是调用父类中定义的成员函数
#include<iostream> using namespace std; class Parent { public: int mi; void add(int v) { mi += v; } void print() { cout << "I'm Parent" << endl; } }; class Child : public Parent { public: int mv; void add(int x, int y) { mv = (x + y); } void print() { cout << "I'm Child" << endl; } }; void how_to_print(Parent* p)//父类的指针 { p->print(); } int main() { Parent p; Child c; how_to_print(&p);//期望是I'm Parent, 结果是I'm Parent how_to_print(&c);//期望是I'm Child, 结果是I'm Parent return 0; }
三、小结
1、子类对象可以当做父类对象使用(赋值兼容)
2、父类指针可以正确指向子类对象
3、父类引用可以正确的代表子类的对象
4、子类中可以重写父类中的成员函数