重载、重写(覆盖)与重定义(隐藏)

news2025/1/18 10:02:08

重载、重写(覆盖)与重定义(隐藏)

  • 重载
  • 隐藏(重定义)
  • 多态:
    • 重写(覆盖)
  • 三者的区别

重载

  • 必须是在一个作用域,函数名相同,参数不同(个数不同,类型不同),才会构成函数重载
// add 函数构成了重载
int add(int a, int b)
{
	cout << "add_int_int" << endl;
	return a + b;
}

int add(double a, int b)
{
	cout << "add_double_int" << endl;
	return a + b;
}

int main()
{
	int x = add(1, 1);
	int y = add(1.0, 2);
	return 0;
}

为什么C++支持重载,而C语言不支持呢?

假设某个C 函数的声明如下:

void foo(int x, int y);

该函数被C 编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int 之类的名字用来支持函数重载和类型安全连接。

隐藏(重定义)

  1. 在继承体系中基类和派生类都有独立的作用域。

  2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏, 也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)

  3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。

  4. 注意在实际中在继承体系里面最好不要定义同名的成员。

// Student的_num和Person的_num构成隐藏关系,可以看出这样代码虽然能跑,但是非常容易混淆
class Person
{
protected:
	string _name = "小李子"; // 姓名
	int _num = 111;    // 身份证号
};

class Student : public Person
{
public:
	void Print()
	{
		cout << " 姓名:" << _name << endl;
		cout << " 身份证号:" << Person::_num << endl;
		cout << " 学号:" << _num << endl;
	}
protected:
	int _num = 999; // 学号
};

void Test()
{
	Student s1;
	s1.Print();
};

int main()
{
	Test();
	return 0;
}
// B中的fun和A中的fun不是构成重载,因为不是在同一作用域
// B中的fun和A中的fun构成隐藏,成员函数满足函数名相同就构成隐藏。
class A
{
public:
	void fun()
	{
		cout << "func()" << endl;
	}
};

class B : public A
{
public:
	void fun(int i)
	{
		A::fun();
		cout << "func(int i)->" << i << endl;
	}
};

void Test()
{
	B b;
	b.fun(10);
};

int main()
{
	Test();
	return 0;
}

多态:

继承中要构成多态还有两个条件:

  1. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
  2. 必须通过基类的指针或者引用调用虚函数

虚函数:即被virtual修饰的类成员函数称为虚函数。

重写(覆盖)

  • 只要虚函数才能重写

  • 派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的 返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。

class Person {
public:
	virtual void BuyTicket() { cout << "买票-全价" << endl; }
};

class Student : public Person {
public:
	virtual void BuyTicket() { cout << "买票-半价" << endl; }

	/*注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写(因
   为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议
   这样使用*/

   /*void BuyTicket() { cout << "买票-半价" << endl; }*/
};

void Func(Person& p)
{
	p.BuyTicket();
}

int main()
{
	Person ps;
	Student st;

	Func(ps);
	Func(st);
	return 0;
}

在这里插入图片描述

虚函数重写的两个例外:

  1. 协变(基类与派生类虚函数返回值类型不同) (了解)

    派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指 针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变。

    class A{};
    
    class B : public A {};
    
    class Person {
    
    public:
     virtual A* f() {return new A;}
    };
    
    class Student : public Person {
    
    public:
     virtual B* f() {return new B;}
    };
    
  2. 析构函数的重写(基类与派生类析构函数的名字不同)

    编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor。

    class Person {
    public:
    	virtual ~Person() { cout << "~Person()" << endl; }
    };
    
    class Student : public Person {
    public:
    	virtual ~Student() { cout << "~Student()" << endl; }
    };
    
    /* 只有派生类Student的析构函数重写了Person的析构函数,下面的delete对象调用析构函数,
    才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数。*/
    
    int main()
    {
    	Person* p1 = new Person;
    	Person* p2 = new Student;
    	delete p1;
    	delete p2;
    	return 0;
    }
    

三者的区别

在这里插入图片描述

没有构成重写就是重定义

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1104144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C复习-基础知识

参考&#xff1a; 里科《C和指针》Bryant, Hallaron 《深入理解计算机系统》何昊&#xff0c;叶向阳《程序员面试笔试宝典》 从hello.c到可执行文件hello 在Unix系统中&#xff0c;从源文件到目标文件的转化是由编译器驱动程序完成的&#xff1a; root> gcc -o hello hel…

RTOS(4)自己的第一个FreeRTOS程序

创建两个任务 什么是任务呢&#xff1f; 对于整个单片机程序&#xff0c;我们称之为application&#xff0c;应用程序。 使用FreeRTOS时&#xff0c;我们可以在application中创建多个任务(task)&#xff0c;有些文档把任务也称为线程 (thread)。 void Task1Function(void *p…

课时4作业3

Description 某人想将手中的一张面值100元的人民币换成10元、5元、2元和1元面值的票子。要求换正好40张&#xff0c;且每种票子至少一张。问&#xff1a;有几种换法&#xff1f; Input 无输入 Output 一个数&#xff0c;表示共有多少种换法 Sample Input 1 无 Sample O…

手写一个PrattParser基本运算解析器1: 编译原理概述

点击查看 基于Swift的PrattParser项目 编译原理概述 编译原理是我们每一个程序猿必须要了解的技能, 编译原理实际上并没有啥高深的技术, 我们如果在做业务开发, 也很少会用到编译开发的知识, 但是编译原理又是我们必备的基础知识之一. 所以我们需要对编译原理的内容有一个大概的…

76.C++ STL list容器

目录 1.什么是list容器 2.list构造函数 3. 元素插⼊和删除操作 4.大小操作 5.赋值操作 6.数据存取操作 7.反转、排序 1.什么是list容器 list 是 C 标准库提供的双向链表容器。它与 vector 和 deque 不同&#xff0c;不是连续的内存块&#xff0c;而是由节点组成的链表结…

C语言——二周目——数据在内存中的存储

目录 一、整数的存储方式 二、浮点数的存储方式 一、整数的存储方式 因为CPU只有加法器&#xff0c;所以对于整型来说&#xff0c;数据在内存中通常采用补码的方式进行储存。 在这里复习一下原码、反码、补码。 正数和无符号数的原码、反码、补码相同&#xff1b; 负数的原…

考察软件开发公司的能力

当公司需要与软件外包公司合作时需要考察软件开发公司的能力和水平&#xff0c;这会涉及到很多方面的因素。需要通过综合考察和了解软件开发公司的能力和水平&#xff0c;选择合适的合作伙伴&#xff0c;确保项目的成功交付。下面分享一些关键步骤和方法&#xff0c;希望对大家…

【JVM】JVM的垃圾回收机制

JVM的垃圾回收机制 对象死亡判断方法引用计数算法可达性分析算法 垃圾回收算法标记清除法复制算法标记整理算法分代算法 Java运行时内存的各个区域,对于程序计数器,虚拟机栈,本地方法栈这三个部分区域而言,其生命周期与相关线程有关,随线程而生,随线程而灭,并且这三个区域的内存…

Excel冻结窗格

1、冻结表格首行 点击菜单栏中的“视图”&#xff0c;选择“窗口”选项卡中的“冻结窗格”下的小三角&#xff0c;再选择“冻结首行”&#xff1b; 2.冻结表格首列 点击菜单栏中的“视图”&#xff0c;选择“窗口”选项卡中的“冻结窗格”下的小三角&#xff0c;再选择“冻结…

图扑智慧仓储数据可视化监控平台

随着市场竞争加剧和市场需求的不断提高&#xff0c;企业亟需更加高效、智能且可靠的仓储物流管理方式&#xff0c;以提升企业的物流效率&#xff0c;减少其输出成本&#xff0c;有效应对市场上的变化和挑战。 图扑软件应用自研 HT for Web 产品搭建的 2D 智慧仓储可视化平台&a…

【轻松搞定】Edge 或 Google 无法上网问题

目录 前言 一、解决 Edge 无法上网的问题 1.1 键盘按下 WIN R 或 右键开始标志&#xff0c;启动运行 1.2 输入 regedit 进入注册表管理 1.3 打开到 \HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft 位置下新建项 Edge 1.4 右键 Edge 新建 DWORD (32) 文件&#xff0c…

<FPGA>好的编码风格(1)--尽量避免组合逻辑环路(Combinational Loops)

什么是组合逻辑环路&#xff1f; 组合逻辑环路&#xff08;Combinational Loops&#xff09;&#xff1a;指组合逻辑的输出信号不经过任何时序逻辑&#xff08;FF等&#xff09;&#xff0c;而是直接反馈到输入节点&#xff0c;从而构成的电路环路。 此外&#xff0c;如果直接将…

【开源分享】基于Html开发的房贷计算器,模仿新浪财经

房贷计算器是一种房贷计算的在线计算Web应用&#xff0c;按用户选择的贷款类型、贷款金额、期限、利率可计算得出每月月供参考、支付利息、还款总额这些信息。本文模仿新浪财经开发的房贷计算器。 作品预览 https://fangdai.gitapp.cn 源码地址 https://github.com/geeeeeee…

Qt5.12.12构建64位QMYSQL数据库驱动“driver not loaded”

在调用QSqlDatabase::open()时,会报错:“driver not loaded” 原因实际上是mysql 的驱动 qsqlmysql.dll 没有成功加载。 所以本篇文章将详细介绍一下:Qt5.12.12如何构建64位QMYSQL数据库驱动。 执行 写在最前,以下出现的文件路径为我自己电脑安装的路径,可根据自己的路…

vim快捷指令

普通模式—>插入模式 i:插入到当前光标的前面&#xff08;insert&#xff09; a:插入到光标的后面&#xff08;append&#xff09; o:插入到下一行 I:插入到行首 A:插入到行尾 O&#xff1a;插入到前一行 H:行首 L:页的最后一行的行首 W:光标跳到下一个单词词首 b:上一个单…

广州华锐互动:VR模拟高楼层建筑应急逃生,提供身临其境的虚拟体验

随着城市化进程的不断加速&#xff0c;高层建筑越来越多地出现在我们的生活中。然而&#xff0c;高层建筑的安全问题也日益凸显。一旦发生火灾、地震等突发事件&#xff0c;如何迅速、安全地逃离高楼成为了人们关注的焦点。近年来&#xff0c;虚拟现实&#xff08;VR&#xff0…

JUC并发编程——ForkJoin与异步回调

ForkJoin &#xff08;分支合并&#xff09; 什么是ForkJoin ForkJoin在JDK1.7出现 &#xff0c;并行执行任务&#xff0c;在大数据量下&#xff0c;能够提高效率 讯飞星火提供的说法&#xff1a; Forkjoin是一种并行计算的算法&#xff0c;用于将一个大任务分解为多个小任务…

【PSO-RFR预测】基于粒子群算法优化随机森林回归预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

MinIO (三) 使用Webhook实时同步文件

前言 使用MinIO的过程中&#xff0c;我们这里遇到个需求&#xff0c;系统需要预览3D文件&#xff0c;前端操作&#xff0c;用浏览3D文件的工具打开3D文件的目录即可实现在线预览功能&#xff0c;这个时候问题来了&#xff0c;MinIO上传文件后进行了编译&#xff0c;如下图 这个…

ardupilot开发 --- 外设适配器、拓展外设、AP_Periph、DroneCAN 、UAVCAN 篇

什么是外设适配器&#xff0c;为什么要拓展外设&#xff1f; 飞控的外设接口有限&#xff0c;如串口只有8个&#xff0c;I^2C只有一个&#xff0c;CAN口只有一个&#xff0c;这些接口数量如果不能满足预期的传感器数量&#xff0c;那么就需要对这些接口进行拓展&#xff0c;外…