1、Override、Overload、Redefine

  • Overload

    重载只能发生在类内部,不能发生在子类和父类的继承中。具体来说,如果子类中有父类同名、同返回值类型,但是不同参数列表,这两个在不同类的函数是不能发生重载的。

  • Override

    重写即就是子类将父类中的方法进行改写。在实例化Parent *p = new Son(),即创建指针类型为父类,指向子类空间的指针,能看到重写和重定义的区别。

  • Redefine

    重定义亦是发生在在继承的过程中,这个和重写容易发生混淆。主要区别根据父类中被重写或重定义的成员函数有无virtual关键字来讨论。如果没有virtual关键字,只要函数名相同,都会发生函数的重定义,或者说隐藏,即子类成员函数隐藏父类同名的成员函数;如果有virtual关键字,首先要保证返回值类型要相同(个人在测试中发现,在子类中,只有将保持返回值类型、函数名相同,才能进行下一步的重写或重定义),再判断是发生重载还是重定义,如果参数列表相同,则发生重写,如果不相同,则是重定义。


2、三者之间的区别

  • 重载 overload

    • 发生在相同的作用域(子类和父类不在同一个作用域)
    • 函数名要相同
    • 参数列表不同,包括参数类型、参数个数、参数的顺序
    • 有无virtual关键字都可以发生
    • 返回值可以不同
  • 重写 override

    • 不同的作用域(两个同名函数分别在父类和子类)
    • 相同的函数名
    • 相同的参数列表
    • 被重写父类中的成员函数必须有关键字'virtual'
    • 相同的返回值类型
    • 被重写的成员函数访问权限可以被修改,publicprotect 或者其他。
  • 重定义 redefine

    • 不同的作用域
    • 函数名相同
    • 返回值类型可以不同(没有关键字virtual的情况),但是如果有virtual关键字,必须保证返回类型相同,否则编译报错。
    • 父类函数没有关键字virtual,参数列表可同可不同;父类函数有关键字virtual,参数列表必须不同。

举个例子说明一下:

class Base{
public:
int param3 = 0;
void func1(){cout<<"This is Base::func1()"<<endl;}
void func2(int a){cout<<"This is Base::func2(int a)"<<endl;}
void func2(char c){cout<<"This is Base::func2(char c)"<<endl;}
void func3(){cout<<"This is Base::func3()"<<endl;}
virtual void func4(){cout<<"This is Base::func4()"<<endl;}
virtual void func5(){cout<<"This is Base::func5()"<<endl;}
virtual int func6(){cout<<"This is int Base::func6()"<<endl;}
}; class Son: public Base
{
public:
int param = 1;
int func1(){cout<<"This is Son::func1()"<<endl;}
void func2(double e){cout<<"This is Son::func2()"<<endl;}
void func3(){cout<<"This is Son::func3()"<<endl;}
void func4(){cout<<"This is Son::func4()"<<endl;}
void func5(int a){cout<<"This is Son::func5(int a)"<<endl;}
// double func6(){cout<<"This is Son::func6()"<<endl;}
}; int main() {
Son s;
Base b;
Base *bp = new Son();
s.func1();
s.func2(1.1);
s.func2('c');
s.func4();
s.func5(2);
cout<<"--------------------------------"<<endl;
b.func1();
b.func2(1);
b.func2('c');
b.func3();
cout<<"--------------------------------"<<endl;
bp->func1();
bp->func2(1);
bp->func2('e');
bp->func3();
bp->func4();
bp->func5();
return 0;
}

输出如下:

This is Son::func1()
This is Son::func2()
This is Son::func2()
This is Son::func4()
This is Son::func5(int a)
--------------------------------
This is Base::func1()
This is Base::func2(int a)
This is Base::func2(char c)
This is Base::func3()
--------------------------------
This is Base::func1()
This is Base::func2(int a)
This is Base::func2(char c)
This is Base::func3()
This is Son::func4()
This is Base::func5()

分别创建子类、父类、指针类型为父类指向子类空间的指针。(1)父类中的func2发生重载,主要在父类内部产生(应该说相同作用域),因为给s.func2('c')传入字符的时候,只会调用子类函数,不会调用父类的func2(char c)。而子类中的func2对父类的func2发生了重定义,并对其做了隐藏,所以调用的时候才会调用到子类的func2(double )。从s.func1()s.func2()s.func3()都发生了重定义,所以在继承的过程中,如果没有virtual关键字,只要函数名相同,不管参数类型、返回值类型,都会发生重定义。(2)针对有virtual关键字的情况,在函数名相同的情况下,首先要保证返回值类型相同,否则编译不过,如果参数列表相同,则发生重写,不同则发生重定义,例如bp->func4()bp->func5(),这里bp调用函数的处理取决于是否重写的函数(虚函数的特性)。


参考文献

c++继承关系中成员函数的重载、重写、重定义之间的区别的更多相关文章

  1. c++ 浅拷贝和深拷贝 指针和引用的区别 malloc(free)和new(delete)的区别 重载重写重定义

    4.malloc(free)和new(delete)的区别 malloc()函数: 1.1 malloc的全称是memory allocation,中文叫动态内存分配. 原型:extern void ...

  2. java继承关系中成员变量,构造方法,成员方法的关系

    Java继承中的成员关系 A:成员变量 a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单写那个名字就访问那个名字! b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ...

  3. C++ 虚函数及重载、重定义、重写

    #include<iostream> usingnamespace std; class BASE { public: BASE()=default; BASE(int publicVal ...

  4. 重载重写重定义-易混淆概念-C++编译器处理方式

    1.函数重载 1)必须在同一个类中进行. 2)子类无法重载父类的函数,父类同名函数将被名称覆盖 3)重载是在编译期间根据参数类型和个数决定函数调用 2.函数重写 1)必须发生于父类与子类之间 2)并且 ...

  5. C++ 学习笔记 (八)重载 重写 重定义以及名字覆盖

    学习C++必定会遇到重载.重写.重定义.概念的东西多也是学习C++蛋疼之处,但是还是得弄懂,学懂了也就不觉得多了. 概念,特点: 重载: 直白点说就是函数名字相同,传参的个数,类型不一样.判断标准在于 ...

  6. C++ 重载 重写 重定义

    重写:存在于类的继承,修饰符是virtual,函数的参数个数,顺序,类型,均相同. 重载:函数的参数列表,类型,顺序不相同. 重定义:对父类的函数进行屏蔽,参数列表可以不相同,没有virtual修饰

  7. C++类成员函数的 重载、覆盖和隐藏区别

    重载:成员函数被重载的特征: (1)相同的范围(在同一个类中): (2)函数名字相同: (3)参数不同: (4)virtual 关键字可有可无. #include <iostream> u ...

  8. C++类成员函数的重载、覆盖和隐藏区别?

    C++类成员函数的重载.覆盖和隐藏区别? a.成员函数被重载的特征:(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无.b.覆盖是指派生类函数覆 ...

  9. C++:类成员函数的重载、覆盖和隐藏区别?

    #include <iostream> class A { public: void func() { std::cout << "Hello" <& ...

随机推荐

  1. PHP中操作数据库的预处理语句

    今天这篇文章的内容其实也是非常基础的内容,不过在现代化的开发中,大家都使用框架,已经很少人会去自己封装或者经常写底层的数据库操作代码了.所以这回我们就来复习一下数据库中相关扩展中的预处理语句内容. 什 ...

  2. Nginx系列(3)- 负载均衡

    负载均衡 Nginx提供的负载均衡策略有两种: 内置策略为轮询.加权轮询.ip hash 扩展策略,就天马行空了,只有你想不到的没有它做不到的 轮询  加权轮询(根据权重来) iphash对客户端请求 ...

  3. javascript base64 encode decode 支持中文

    * 字符编码 ** 一定要知道数据的字符编码 ** 使用utf-8字符编码存储数据 ** 使用utf-8字符编码输出数据 * Crypto.js 支持中文 Base64编码说明 Base64编码要求把 ...

  4. svn的应用

    SVN 如何来进行多人协作开发? 在实际工作中,通常是一个小组或者一个团队一起开发同一个项目,不同的人开发不同的功能模块,有一个公共的地方存放项目代码. 如果多个人同时对同一个文件做了修改,比如按照分 ...

  5. Appium WebView控件定位

    背景 移动应用可以粗分为三种:原生应用(native app), 网页应用(web app,或HTML5 app),以及它们的混血儿--混合模式移动应用(hybrid app). 什么是Hybrid ...

  6. jmeter加密解密(加密篇)

    最近刚好在弄jmeter加密解密,可以分享下.(有一段时间没写了,有点不知道从何写起,这篇写的有点乱o(╥﹏╥)o) 需求是:接口中的请求体的部分参数需要先加密再请求,返回的结果中部分字段需解密. 1 ...

  7. 使用亚马逊服务器报错:Signature not yet current: 20190726T070253Z is still later than 20190726T070246Z (20190726T065746Z + 15 min.)时间不同步的解决办法

    1.首先获取亚马逊的时间: $ curl http://s3.amazonaws.com -v 2.更改当前服务器时间,使之与亚马逊时间同步 $ date -s 'xxxx-xx-xx xx:xx:x ...

  8. Jupyter lab 配置记录,xpython + R 语言

    install.packages(c("repr", "IRdisplay", "evaluate", "crayon" ...

  9. [转载]CentOS 7 创建本地YUM源

    本文中的"本地YUM源"包括三种类型:一是直接使用CentOS光盘作为本地yum源,优点是简单便捷,缺点是光盘软件包可能不完整(centos 7 Everything 总共才6.5 ...

  10. C#实例:datagridview单元格合并

    这是替C#微信交流群群友做的一个小实例,目的就是在datagridview选择对应行以后,点击button后获取对应行的ip,并执行相应的操作,其实我觉得这样的话button没必要非放置到datagr ...