条款33:避免掩盖继承而来的名称

2024-03-28 11:18

本文主要是介绍条款33:避免掩盖继承而来的名称,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这其实是一个作用域带来的问题:局部变量会掩盖同名的外围变量。注意,只要同名就会被掩盖,与类型无关:

void main()  
{  int a = 10;{double a = 0.1;cout<<a<<endl;//结果为0.1}cout<<a<<endl;//结果为10
}
而对于继承派生体系也是如此,因为派生类继承了基类的所有public部分,所以:


class Base
{
public:virtual void f1() = 0;virtual void f2(){cout<<"Base f2"<<endl;}
};class Drived: public Base
{
public:void f1(){f2();}void f2(){cout<<"Drived f2"<<endl;}
};
//main.cppDrived d;d.f1();

中f1调用的是派生类的f2,如果想调用基类的f2,那么必须指明作用域:

	void f1(){Base::f2();}



明白了作用域关系之后,让我们看一个例子:

class Base
{
public:virtual void f1() = 0;virtual void f2(){cout<<"Base f2"<<endl;}void f3(){cout<<"Base f3"<<endl;}void f3(double d){cout<<"Base f3 double"<<endl;}//重载
};class Drived: public Base
{
public:void f1(){cout<<"Drived f1"<<endl;}void f2(int i){cout<<"Drived f2"<<endl;}void f3(){cout<<"Base f3 int"<<endl;}};
此时
	Drived d;d.f2(1);//正确//错误d.f2();
因为派生类中的f2(int i)屏蔽了基类中的f2()。同理还有f3(int i)函数。f1函数由于抽象类声明了接口为f1(),所以没有改变。这说明,这种关系的掩盖只取决于函数的名字,与函数的形参、返回值类型,是否为虚函数之类的无关。
总之,我们发现基类的函数在这里不能使用了:即is-a关系不再成立了!为了让is-a关系继续满足,你可以通过声明来实现:
public:using Base::f2;using Base::f3;void f1(){cout<<"Drived f1"<<endl;}int f2(int i){cout<<"Drived f2"<<endl;return 1;}void f3(int i){cout<<"Drived f3"<<endl;}

此时:

	d.f3();d.f3(1);d.f3(1.1);

都是正确的。
但是,using声明带来的问题是:假如我只想使用基类的f3的某个特定版本,但是这里会把f3的所有版本暴漏给派生类。怎么办呢?有一种称为转交函数的办法,在派生类中定义:

	void f3(double i){Base::f3(i);}

此时就避免了基类中的f3()函数暴漏出来了。
总之,派生类内的名称会掩盖基类中的名称,如果不想让这些名称被掩盖,可以使用using声明或者使用转交函数。

这篇关于条款33:避免掩盖继承而来的名称的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/855464

相关文章

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。

如何来避免FOUC

FOUC(Flash of Unstyled Content)是指在网页加载过程中,由于CSS样式加载延迟或加载顺序不当,导致页面出现短暂的无样式内容闪烁现象。为了避免FOUC,可以采取以下几种方法: 1. 优化CSS加载 内联CSS:将关键的CSS样式直接嵌入到HTML文档的<head>部分,这样可以确保在页面渲染之前样式就已经加载和应用。提前引入CSS:将CSS文件放在HTML文档的<he

argodb自定义函数读取hdfs文件的注意点,避免FileSystem已关闭异常

一、问题描述 一位同学反馈,他写的argo存过中调用了一个自定义函数,函数会加载hdfs上的一个文件,但有些节点会报FileSystem closed异常,同时有时任务会成功,有时会失败。 二、问题分析 argodb的计算引擎是基于spark的定制化引擎,对于自定义函数的调用跟hive on spark的是一致的。udf要通过反射生成实例,然后迭代调用evaluate。通过代码分析,udf在

七、Maven继承和聚合关系、及Maven的仓库及查找顺序

1.继承   2.聚合   3.Maven的仓库及查找顺序

Qt: 详细理解delete与deleteLater (避免访问悬空指针导致程序异常终止)

前言 珍爱生命,远离悬空指针。 正文 delete 立即删除:调用 delete 后,对象会立即被销毁,其内存会立即被释放。调用顺序:对象的析构函数会被立即调用,销毁该对象及其子对象。无事件处理:如果在对象销毁过程中还涉及到信号和槽、事件处理等,直接 delete 可能会导致问题,尤其是在对象正在处理事件时。适用场景:适用于在确定对象已经不再被使用的情况下,并且不涉及异步处理或事件循环中的

Oracle 查看表空间名称及大小和删除表空间及数据文件方法

--1、查看表空间的名称及大小  SELECT t.tablespace_name, round(SUM(bytes / (1024 * 1024)), 0) ts_size  FROM dba_tablespaces t, dba_data_files d  WHERE t.tablespace_name = d.tablespace_name  GROUP BY t.tablespace_na

理解C++全局对象析构顺序与 IPC 资源管理:避免 coredump

文章目录 0. 概述1. 问题背景2. 问题分析3. 解决方案:手动释放资源4. 深入剖析:为什么手动调用 `reset()` 有效?5. 延伸思考:如何避免全局对象带来的问题?6. 总结 0. 概述 在编写 C++ 程序时,使用全局或静态对象有时可能会导致不可预期的崩溃(如 coredump)。这类崩溃通常源于对象的析构顺序、资源的管理方式,以及底层资源(如 IPC 通道或共

Java应用对接pinpoint监控工具的时候,应用名称长度超出限制而导致接入失败

一、背景 java应用需要接入pinpoint,同一个虚拟机上的其他应用接入成功,唯独本应用不行。 首先排除是pinpoint agent的问题,因为其他应用都正常。 然后,我就对比二者的启动脚本。 -javaagent:/opt/pinpoint/pinpoint-bootstrap.jar -Dpinpoint.agentId=DA301004_17 -Dpinpoint.applic

【JavaScript】方法属性的匿名函数是匿名函数么(附:获取当前执行函数名称的方法)

var ninja = {shout: function(){console.log("hello");}}   有些人可能认为,将匿名函数赋值给名为shout的属性也就相当于给它取了名字,其实这是不正确的理解。shout是属性的名称,而不是函数自身的名称。这一点可以通过检查函数的name属性来验证。 下面是一些测试实例,请自行思考(前两个均为匿名函数):