c++继承关系中成员函数的重载、重写、重定义之间的区别
1、Override、Overload、Redefine
- Overload 
 重载只能发生在类内部,不能发生在子类和父类的继承中。具体来说,如果子类中有父类同名、同返回值类型,但是不同参数列表,这两个在不同类的函数是不能发生重载的。
- Override 
 重写即就是子类将父类中的方法进行改写。在实例化- Parent *p = new Son(),即创建指针类型为父类,指向子类空间的指针,能看到重写和重定义的区别。
- Redefine 
 重定义亦是发生在在继承的过程中,这个和重写容易发生混淆。主要区别根据父类中被重写或重定义的成员函数有无- virtual关键字来讨论。如果没有- virtual关键字,只要函数名相同,都会发生函数的重定义,或者说隐藏,即子类成员函数隐藏父类同名的成员函数;如果有- virtual关键字,首先要保证返回值类型要相同(个人在测试中发现,在子类中,只有将保持返回值类型、函数名相同,才能进行下一步的重写或重定义),再判断是发生重载还是重定义,如果参数列表相同,则发生重写,如果不相同,则是重定义。
2、三者之间的区别
- 重载 overload - 发生在相同的作用域(子类和父类不在同一个作用域)
- 函数名要相同
- 参数列表不同,包括参数类型、参数个数、参数的顺序
- 有无virtual关键字都可以发生
- 返回值可以不同
 
- 重写 override - 不同的作用域(两个同名函数分别在父类和子类)
- 相同的函数名
- 相同的参数列表
- 被重写父类中的成员函数必须有关键字'virtual'
- 相同的返回值类型
- 被重写的成员函数访问权限可以被修改,public、protect或者其他。
 
- 重定义 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++继承关系中成员函数的重载、重写、重定义之间的区别的更多相关文章
- c++ 浅拷贝和深拷贝    指针和引用的区别    malloc(free)和new(delete)的区别  重载重写重定义
		4.malloc(free)和new(delete)的区别 malloc()函数: 1.1 malloc的全称是memory allocation,中文叫动态内存分配. 原型:extern void ... 
- java继承关系中成员变量,构造方法,成员方法的关系
		Java继承中的成员关系 A:成员变量 a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单写那个名字就访问那个名字! b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ... 
- C++ 虚函数及重载、重定义、重写
		#include<iostream> usingnamespace std; class BASE { public: BASE()=default; BASE(int publicVal ... 
- 重载重写重定义-易混淆概念-C++编译器处理方式
		1.函数重载 1)必须在同一个类中进行. 2)子类无法重载父类的函数,父类同名函数将被名称覆盖 3)重载是在编译期间根据参数类型和个数决定函数调用 2.函数重写 1)必须发生于父类与子类之间 2)并且 ... 
- C++ 学习笔记 (八)重载 重写 重定义以及名字覆盖
		学习C++必定会遇到重载.重写.重定义.概念的东西多也是学习C++蛋疼之处,但是还是得弄懂,学懂了也就不觉得多了. 概念,特点: 重载: 直白点说就是函数名字相同,传参的个数,类型不一样.判断标准在于 ... 
- C++ 重载 重写 重定义
		重写:存在于类的继承,修饰符是virtual,函数的参数个数,顺序,类型,均相同. 重载:函数的参数列表,类型,顺序不相同. 重定义:对父类的函数进行屏蔽,参数列表可以不相同,没有virtual修饰 
- C++类成员函数的 重载、覆盖和隐藏区别
		重载:成员函数被重载的特征: (1)相同的范围(在同一个类中): (2)函数名字相同: (3)参数不同: (4)virtual 关键字可有可无. #include <iostream> u ... 
- C++类成员函数的重载、覆盖和隐藏区别?
		C++类成员函数的重载.覆盖和隐藏区别? a.成员函数被重载的特征:(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无.b.覆盖是指派生类函数覆 ... 
- C++:类成员函数的重载、覆盖和隐藏区别?
		#include <iostream> class A { public: void func() { std::cout << "Hello" <& ... 
随机推荐
- Java实现文件下载
			一.html <button class="ui-btn ui-btn-primary left20" onclick="downloadXlsTemplate() ... 
- 如何解决SVN Upgrade working copy问题
			电脑还原系统后,安装了最新版本的SVN,发现原来在svn检出的文件夹出现了SVN Upgrade working copy,没有commit ,没有update. 在网上查询到:出现这个的原因是因为你 ... 
- django ORM教程(转载)
			Django中ORM介绍和字段及字段参数 Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简 ... 
- python 建站教程
			主端:安装nginx uwsgi django pymysql mysql安装mysql到http://repo.mysql.com/里面找 mysql57-community-release-el7 ... 
- GDOI2021划水记
			Day0 上午有意志行,一大早就醒了,然后走了五个小时脚痛.中午洗澡,宿舍轮流看巨人最终话然后聊了一个小时? 下午老师带着我和全爷先开溜,宿舍好像很破旧还还没得充电,领了牌牌和斐爷去吃饭. 然后六点多 ... 
- MySQL、Redis、MongoDB网络抓包工具
			简介 go-sniffer 可以抓包截取项目(MySQL.Redis.MongoDB)中的请求并解析成相应的语句,并格式化输出.类似于在之前的文章 MySQL抓包工具:MySQL Sniffer[转] ... 
- 深度学习--GAN学习笔记
			生成模型 WGAN Blog GAN 推荐学习网站 生成模型 什么是生成模型? GMM: 用来做聚类,(非监督学习) NB(朴素贝叶斯):(监督学习,可以用来做垃圾邮件分类) Logistics 回归 ... 
- c++ 的学习 构造函数1
			1. 构造函数(也叫构造器),在对象创建的时候自动调用,一般用于完成对象的初始化工作 2.一旦自定义了构造函数,必须用其中一个自定义的构造函数来初始化对象 就是有多个的话 根据参数编译器自行选 ... 
- k8s deployment controller源码分析
			deployment controller简介 deployment controller是kube-controller-manager组件中众多控制器中的一个,是 deployment 资源对象的 ... 
- 你了解一条sql的执行顺序吗
			sql是后端开发人员经常碰到的问题,我们经常会写这样的sql:select name,id from student where id=12 order by id desc,把这条sql放到数据库中 ... 
