重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
在子类继承父类后,子类对象便可以当做父类对象使用了(兼容性)。包括:1、子类对象可以直接赋值给父类对象;2、子类对象可以直接初始化父类对象;3、父类对象可以直接指向子类对象;4、父类引用可以直接引用子类对象。那么我们来编程看看子类对象的兼容性
创新互联公司专注于城阳网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供城阳营销型网站建设,城阳网站制作、城阳网页设计、城阳网站官网定制、微信小程序服务,打造城阳网络公司原创品牌,更为您提供城阳网站排名全网营销落地服务。#include#include using namespace std; class Parent { public: int mi; void add(int v) { mi += v; } void add(int a, int b) { mi += (a + b); } }; class Child : public Parent { public: int mv; void add(int a, int b, int c) { mv += (a + b + c); } }; int main() { Parent p; Child c; p = c; Parent p1(c); Parent& rp = c; Parent* pp = &c; rp.mi = 100; rp.add(5); rp.add(10, 10); //pp->mv = 1000; //pp->add(1, 10, 100); return 0; }
我们先来看看第 38 行将子类对象 c 直接赋值给父类对象 p,这样编译会通过吗?还有第 40 行的初始化操作。再将子类对象 c 赋值给父类对象的引用 rp,将父类对象的指针 pp 指向对象 c 的地址。通过 rp 调用父类对象的成员变量和成员函数,看看会报错吗?照理说这块应该会发生同名覆盖,我们看看编译结果
编译是通过的,也就证明没有发生同名覆盖。那么我们再来将第 49 和 50 行的注释去掉,看看通过指针 pp 指向的子类对象 c 直接调用子类对象的成员变量和成员函数会通过吗?
我们看到编译出错了。下来我们来说下当使用父类指针(引用)指向子类对象时,子类对象便退化为父类对象,只能访问父类中定义的成员,可以直接访问被子类覆盖的同名成员。这也就不难解释上面没有发生同名覆盖以及通过指针来调用子类对象的成员变量和成员函数出错的情况了。
在子类中可以重定义父类中已经存在的成员函数,这种重定义发生在继承中,叫做函数重写。函数重写是同名覆盖的一种特殊情况。当函数重写遇上赋值兼容会发生什么呢?我们通过是来代码来分析下
#include#include using namespace std; class Parent { public: void print() { cout << "I'm Parent!" << endl; } }; class Child : public Parent { public: void print() { cout << "I'm Child!" << endl; } }; void how_to_print(Parent* p) { p->print(); } int main() { Parent p; Child c; p.print(); // I'm Parent! c.print(); // I'm Child! cout << endl; how_to_print(&p); // I'm Parent! how_to_print(&c); // I'm Child! return 0; }
我们分别在父类和子类中定义 print 函数,打印相关信息。我们期望的是 p.print() 打印的是 I'm Parent!;c.print() 打印的是 I'm Child!;在调用全局函数 how_to_print() 时,如果传入的是父类指针,我们期望打印的是 I'm Parent!,如果传入的是子类指针,则打印的是 I'm Child!。下来我们来编译看看结果
我们直接调用的时候打印的是对的,但是在传入对象的时候,打印的是错的。我们传入的是子类对象,但是打印出来的是父类的函数,我们会不会很奇怪呢?在编译期间,编译器只能根据指针的类型判断所指向的对象,根据赋值兼容,编译器认为父类指针指向的是父类对象。因此,编译结果只可能是调用父类中定义的同名函数。那么在编译到 how_to_print(Parent* p) 这个函数时,编译器不可能知道指针 p 究竟指向了什么。但是编译器没有理由报错。于是乎,编译器认为最安全的做法是调用父类的 print 函数,因为父类和子类肯定都有相同的 print 函数。因此便出现了这个编译结果,那么编译器的处理方法是合理的吗?是期望的吗?显然从安全的角度来说,它的处理是合理的,但却不是我们所期望的。在后面我们会继续讲解这个问题的。
通过对同名覆盖的学习,总结如下:1、子类对象可以当做父类对象使用(赋值兼容);2、父类指针可以正确的指针子类对象;3、父类引用可以正确的代表子类对象;4、子类中可以重写父类中的成员函数。
欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。