浅析C++重载覆盖隐藏以及虚函数
来源:互联网 发布:上海网络广播 编辑:程序博客网 时间:2024/05/21 22:21
C++里面重载覆盖隐藏的概念经常被提及,在很多C++测试题目里面也一直有遇到,每次做这类型的题目总感觉没有彻底搞清楚,故在这里做一个总结,以后遇到类似的问题能够轻易解决。首先来看看<<高质量C/C++编程指南>>作者对几个概念的描述:
重载:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖:
(1)不同的范围(父子类中)
(2)函数名称相同
(3)参数相同
(4)基类必须有virtual关键字
隐藏:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
重载发生在一个类中,覆盖发生在子类重新实现了父类的虚函数。一般来说,只要记住了重载和覆盖,遇到其他情况只要函数同名基本可以判定为隐藏。隐藏顾名思义就是还可以被找出来,而覆盖就不存在了。重载不能仅仅根据返回值不一致来区分两个重载函数。下面看几个例子。
example1:
class base{public:int test(char x){printf("base::test(char) %d \n", x);}virtual int test(int x){printf("base::test(int) %d \n", x);}};class derived: public base{public:int test(char x){printf("derived::test(char) %d \n", x);}int test(int x){printf("derived::test(int) %d \n",x);}virtual int test(float x){printf("derived::test(float) %f \n",x);}};int main(void){derived obj;base* pobj = &obj;derived* p2obj = &obj;pobj->test((char)(100)); //(1)p2obj->test((char)(100)); //(2)((derived*)pobj)->test((char)(100));//(5)pobj->test(100); //(3)p2obj->test(100); //(4)return (0);}
输出:
base::test(char) 100 derived::test(char) 100 derived::test(char) 100 derived::test(int) 100 derived::test(int) 100
说明:Base类中,因参数类型不相同,两个test的关系为重载。derived类中三个test也为重载关系,其中derived的test(char)隐藏了基类test(char),test(int)覆盖了基类虚函数virtual int test(int)的实现,也可以说在derived的虚函数表里面用自身的test(int)替换了继承而来的test(int)。
1>pobj->test((char)(100));参数类型为char,pobj类型为base*,基类test(char)与派生类test(char)的关系为派生类隐藏了基类函数。此时pobj指针类型为base*所以此时调用的是基类的test(char)函数,如果此时要调用派生类的test(char),可以把pobj抢转为derived*类型如(5)所示。同理(2)调用的是derived中的函数。
2>在derived的虚函数表中,derived中test(int)覆盖了继承而来的base中test(int)函数。(3)用基类指针指向派生类,并调用被覆盖的虚函数,发生了动态绑定,显然调用的是派生类中的test(int)。至于(4)指针指向类型为drived*调用的也是test(int)函数。
example2:
class Father { public: void name(){cout<<"Father name"<<endl;} virtual void call(){cout<<"Father call"<<endl;} }; class Son:public Father { public: void name(){cout<<"Son name"<<endl;} virtual void call(){cout<<"Son call"<<endl;} }; int main() { Son *s1 = new Son(); Father *f1 = (Father *)s1; f1->call(); //son call (1) f1->name(); //father name (2) ((Son*)f1)->call(); //son call (3) ((Son*)f1)->name(); //son name (4) Father *f2 = new Father(); Son *s2 = (Son*)f2; s2->call(); //father call (5) s2->name(); //son name (6) ((Father*)s2)->call();//father call(7) ((Father*)s2)->name();//father name(8) return 0; }
输出:
Son callFather nameSon callSon nameFather callSon nameFather callFather name说明:son中的name隐藏了father中的name,son中的call覆盖了father中的call。(1)发生了动态绑定输出son call。(2)指针类型是father*因此输出father name。(3)动态绑定与指针实际指向的类型相关而与指针类型无关故输出son call。(4)由于当前指针类型为father*前面(2)输出father name,而这里把指针类型转为son*相当与把隐藏的name函数显式调用,因此输出son name。(5)输出father call。(6)输出son name。(7)输出father call。(8)输出father name。
小结:如果函数的关系为隐藏,则判别指针(引用)类型(->符号左边的类型),根据指针类型决定调用的是哪个函数。如果函数关系为隐藏,则判断指针具体指向的类型,根据具体指向来判断调用的函数。PS:有关C++虚函数具体解析请看这里 :虚函数表解析。
____________The End。
- 浅析C++重载覆盖隐藏以及虚函数
- 函数重载、函数覆盖以及函数隐藏
- 【C++】成员函数的重载,覆盖,隐藏
- C++ 覆盖 重载 隐藏 浅析
- 浅析重载、隐藏与覆盖
- 函数重载、覆盖、隐藏
- 函数重载、覆盖、隐藏
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- iOS 搭建 XMPP实现环境
- cpu arch之msp pic
- MySQL 递归查询 当前节点及子节点
- UML类图几种关系的总结
- 我收藏的重要站点
- 浅析C++重载覆盖隐藏以及虚函数
- 对自我的总结
- Linux shell编程 1 ---- shell脚本编程基础
- 使用PL/SQL Developer远程连接到oracle 11g
- 数组全排列算法(二)整型数组全排列——递归算法
- jsp之session对象
- 使用HTML5技术开发的超酷颜色选择器
- 带索引的mapReduce
- BNU1064:人品问题