解析C++中重载,隐藏以及覆盖

我们在学习C++过程中,关于三个词,重载,隐藏,覆盖,那么他们分别做了什么呢?且看下文详解

1:基本概念:

重载:在同一作用域下,函数名相同,但是参数列表不同(参数个数,类型,顺序的几个函数,构成重载关系。重载不能靠返回值类型来判断。

示例:


class A
{
public:
   <1> void show(int i);   //1,2,3,4这四个函数都在类A的作用域下且函数名相同,参数列表不同,构成重载
   <2> void show(double i);      
   <3> void show(int i, double j);
   <4> void show(double i, int j);
   <5> int show(int i);         //错误,非重载。注意重载不关心函数返回类型。
};

隐藏:也叫重定义,是指派生类的函数屏蔽了与其同名的基类函数(注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏)。

具体的来说,就是当如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。另一点如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字,此时,基类的函数被隐藏。所以在派生类中我们只能访问派生类自己的成员方法,如果我们想要在派生类中访问基类的成员方法,我们就需要加上基类的作用域(因为在派生类中,基类的成员方法也被继承了)。

示例:

class Base
{
public:
    void show();     //Base 中的两个函数构成重载
    void show(int a);
protected:
    int ma;
};

class Derive:public Base
{
public:
    void show();   //与Base中的第一个show名字且参数列表相同,但是并没有virtual,所以与Base中的那两个函数都构成隐藏
private:
    int mb;
};

int main()
{
    Derive b;
    b.show();    //调用的是Derive中的show
    b.Base::show();  //因为加了作用域,所以就是调用的Base中的不带参数的show
    b.Base::show(3); //加了作用域,调用Base中的带整形参数的show
    b.show(3);  //错误,因为Derive中没有带一个整形参数的show函数
    return 0;
}

覆盖:也叫重写,派生类重新定义基类中相同名称和参数的虚函数,函数特征相同,但是具体实现不同,主要是在继承关系中出现的。具体来说就是要构成覆盖就得满足基类中有virtual修饰的函数,而在派生类中有与基类中的虚函数同名且同参数列表的函数,那么派生类中的的该函数就会将基类中的函数覆盖,调用时无法调用基类中的函数。在子类中定义了一个与父类虚函数完全相同的函数,那么这个子类的函数就是重写了父类的虚函数,此时这个子类的函数就是虚函数,即使派生类的这个函数不显示的加上virtual修饰,编译器也会默认为虚函数。(但是我们要知道,其覆盖的是派生类的虚函数表中的函数地址)

示例:

class Base
{
public:
    void show();     //Base 中的两个函数构成重载
    virtual void show(int a);
protected:
    int ma;
};

class Derive:public Base
{
public:
    void show();   //并不会发生覆盖,因为基类中的无参show函数并不是虚函数
    void show(int b);   //与Base中的第二个show函数名字且参数列表相同,并且基类中该函数是虚函数,所以这个函数也会成为虚函数,并且会发生覆盖,将带参的show函数重写
private:
    int mb;
};

int main()
{
    Derive b;
    Base *p=&b; //用基类指针指向派生类对象,但是不能反过来
	p->show();  //因为p是Base *类型,所以他会在派生类中查看继承过来的Base部分,就会调用Base中的无参show函数,这是静态绑定,在编译器已经决定了
	static_cast<Derive *>(p)->show(); //如果要调用Derive中的函数,就需要将类型强转,当然我们最好用dynamic_cast
    p->show(5);  //这里却并不会调用Base中的带参show函数,因为基类中的带参show函数是虚函数,在派生类的虚表中已经覆盖掉了。动态绑定
    return 0;
}

运行结果: 

 

ps:基类的指针指向派生类对象,指向的是派生类中基类的部分,此时这个基类的指针调用在派生类中对基类中中虚函数重写的虚函数,调用的是派生类的虚函数。 相反,用一个基类的指针指向基类的对象,那么这个基类的指针调用该重写的虚函数,调用的是基类的虚函数,这是因为在基类中只有这一个函数。用派生类的指针调用该函数也调用的是派生类自己的函数。这也即是覆盖的含义,将派生类中的继承来的函数给覆盖掉。

补充:基类的指针能够指向派生类,这是因为派生类由自己的一部分和继承基类部分组成,基类的指针指向派生类其实是指向派生类中的基类部分。相反,派生类的指针无法指向基类。实际上,在虚表中还存在运行时的类型信息,所以我们p是Base*类型,但是我们解引用的*p却是Derive类型,但前提必须是有虚函数哦。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值