C++之对待继承得到的名字

一.结论

  • 派生类中变量或者函数名字覆盖基类的名字,是公有继承所不希望的
  • 使用using声明或者转调函数可以使隐藏的函数名字或者变量名字可见

二.详细说明

为了说明以上的结论,首先需要说明隐藏、覆盖以及作用域等概念,接着举例说明隐藏、覆盖以及作用域等带来的问题,最后以解决方法解决以上问题。

2.1 隐藏、覆盖和作用域

作用域:从字面上理解,某事物起作用的地方,比如说白天太阳能够照射的地方,能看到太阳,而照不到的地方就看不到太阳,能够看到太阳的地方就是太阳的作用域。比较官方的定义如下:

作用域:程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域 —百度百科

隐藏:从字面上理解就是,因为某事物的到来,一些事物被隐藏起来了,但是可以通过一些办法让它显现出来,比如还以上面的例子,太阳照射不到的地方通过镜子将阳关反射到被隐藏事物的地方(转调),隐藏的事物亦可以看到太阳了。官方的定义:

派生类将继承的基类的同名的成员变量和成员方法隐藏起来,通过派生类只能访问到自己的成员变量和成员方法。

覆盖: 从字面上理解,某些事物因为有冲突,在一些作用域下不能同时出现,在某一片阳光下,要么只能出现事物A,要么只能出现事物B。

覆盖往往与继承的类中有virtual修饰的函数有关。virtual修饰的函数为虚函数。而覆盖就是基类中有virtual修饰的函数,且在派生类中有与基类中的虚函数同名且同参数列表的函数,那么派生类中的的该函数就会将基类中的函数覆盖,调用时无法调用基类中的函数

2.2.局部变量和全局变量选择

int val = 1; // global valuevoid main(){ double val = 2.5; // local value std::cout << val << std::endl; // out 2.5 std::cout << ::val << std::endl; // out 1}

运行结果:

2.51

当编译器在cout处输出val时,将首先查找 TestFun 的作用域中是否有名字 val ,如果有则它将直接输出这个变量的值,如果没有则会向TestFun之外的地方查找val符号,找到则直接输出。此处输出2.5,局部的val变量覆盖了全局的val变量。如果要想使用全局变量val,需要添加作用域::val。

此处局部变量掩盖全局变量,若想使用全局变量可添加作用域的形式使用

2.3. 继承时变量选择

有如下类继承关系,基类中包含纯虚函数、虚函数和非虚函数,派生类公有继承基类,包含基类中非虚函数的同名同参函数和独有函数,如下:

class Base {private: int val; public: virtual void mFun1() = 0; virtual void mFun1(double) { std::cout << "Base mFun1 with param double" << std::endl; } virtual void mFun2() { std::cout << "Base mFun2" << std::endl; } void mFun3() { std::cout << "Base mFun3" << std::endl; } void mFun3(float) { std::cout << "Base mFun3 with param float" << std::endl; }};class Derived: public Base {public: virtual void mFun1() { std::cout << "Derieved mFun1" << std::endl; } void mFun3() { std::cout << "Derieved mFun3" << std::endl; mFun2(); } void mFun4() { std::cout << "Derieved mFun4" << std::endl; mFun3(); // mFun3(1.25); // no matching function }};

1.在构建派生类实例时,调用同名同参的非虚函数mFun3时,其搜索路径是,先搜索mFun3内部是否找到mFun2,如果没有找到则在类Derived中查找mFun2,如果类内有找到则继续向上Base类中查找mFun2,如果没有找到则继续向本文件中查找mFun2等等。此处mFun2在Base类中找到,如下例子:

int main() { Derived der; der.mFun3(); return 0;}

运行结果:

Derieved mFun3Base mFun2

2.在构建派生类实例时,调用函数mFun4时,mFun4中现调用的mFun3只会调用派生类Derived中的mFun3,且无法调用带参数的mFun3,否则编译时会报no matching function错误,实例中调用带参的mFun3一样报错,因为派生类中的函数覆盖了基类中的同名函数包括不同参数,换句话说派生类中的同名函数覆盖了了Base::mFun1和Base::mFun3。 如下例子:

int main() { Derived der; der.mFun1(); // call Derived mFun1 der.mFun4(); // call Derived mFun4 // der.mFun3(1.25); // no matching function return 0;}

运行结果

Derieved mFun4Derieved mFun3Base mFun2

从上面的两个例子中可以发现一个很明显的问题,由于同名覆盖的情况,导致在派生类中无法调用基类中同名不同参数的函数, 以下就是一些解决办法

2.4 使用using声明

使用using 声明可以将作用域从原先限定的地方拓展到声明的地方,增加其使用范围,例子如下:

// Base基类同上class Derived: public Base {public: using Base::mFun3; virtual void mFun1() { std::cout << "Derieved mFun1" << std::endl; } void mFun3() { std::cout << "Derieved mFun3" << std::endl; mFun2(); } void mFun4() { std::cout << "Derieved mFun4" << std::endl; mFun3(); // mFun3(1.25); // no matching function }};

使用Demo进行测试:

int main() { Derived der; der.mFun1(); // call Derived mFun1 der.mFun1(1.0); // call Base mFun1 der.mFun4(); // call Derived mFun4 der.mFun3(); // call Derived mFun3 der.mFun3(1.25); // call Base mFun3 return 0;}

运行结果:

Derieved mFun1 // der.mFun1();Base mFun1 with param double // der.mFun1(1.0);Derieved mFun4 // der.mFun4();Derieved mFun3Base mFun2Derieved mFun3 // der.mFun3();Base mFun2Base mFun3 with param float // der.mFun3(1.25);

从结果中可以看出使用using声明将基类中的函数作用域拓展到了派生类中,在派生类中可以直接使用,假如派生类中只想继承基类中不带参数的函数该如何呢?这时使用using声明可能会将带参数的函数同时给引入进来,而无法解决此类问题。此处可以通过转调函数实现,如下。

2.5 使用转掉函数

私有继承加上转调函数可以完美解决using声明不能解决的只继承带不参数的函数,例子如下:

// Base基类同上void Base::mFun1(){ std::cout << "Base mFun1" << std::endl;}class Derived: private Base {public: virtual void mFun1() { std::cout << "Derieved mFun1" << std::endl; Base::mFun1(); }};

使用Demo进行测试

int main() { Derived der; der.mFun1(); // call Derived mFun1 // der.mFun1(1.0); // error no matching function return 0;}

运行结果:

Derieved mFun1Base mFun1

参考:

1.Effective C++ Item33

2.解析C++隐藏与覆盖Oragen的博客-CSDN博客c++隐藏和覆盖

3.作用域_百度百科 (baidu.com)

备注:

欢迎大家多多指教,喜欢的大家可以点击关注本账号或者微信公众号:软件系统安全,后续将不定期更新C++相关的内容

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年8月8日
下一篇 2022年8月8日

相关推荐

  • 1.4 chkconfig 命令

    1.4 chkconfig 命令 chkconfig命令的功能强大,可以设置系统中所有服务在各个运行级别中的启动状态,当然也包括受xinetd服务管理的服务。 1.管理服务在运行级…

    2022年6月21日
  • 风筝写出的诗

    风与筝,离不开彼此的过客。有风吹,才有风筝飞,有风筝飞才有风的多彩。 《风筝》 ——归谷子 别追逐了 因为春天已过 因为我随着风沉浮在仓促的旅途里 望尽了千百种路 如丝般缠绕着我不…

    2022年5月2日
  • 坐车

    随机而言 今天下午坐別人车到一个地方游玩,路上行人特别多车辆也不少往热闹市区除了上超市就是逛商店别无去处上超市里还需扫场所码,显的更加麻烦,还不如上郊区人少的地方游玩一下不好吗?有…

    2022年8月12日
  • 怎么区分手机的好坏,别过分看重处理器,这3点地方同样重要

    智能手机对于我们这个时代的人来说,无疑是一个非常重要的工具,工作、购物、出行、掌握新鲜资讯等等,都需要用到它。面对市场上形形色色的手机来说,大家都想买一款“好手机”,那怎样才能“好…

    2022年6月24日
  • 沈腾瘦下来了 张俪在线提问:哪家普拉提 有名字吗?

    17日,沈腾瘦下来了话题上热搜,前段时间沈腾被爆料在练普拉提,近照中的沈腾身形挺拔瘦了许多,网友感叹“这就是普拉提的力量吗?”女星张俪也在线好奇“哪家普拉提,有名字吗?”

    2022年10月19日
  • 如何拯救楼市!房价下跌什么时候是个头?

    社会有一种无形的力量在进行操控,这种力量就是社会发展带来的趋势。 这个趋势,创造了无数的财富红利。 因为,趋势是一种客观规律,不以人的意志为转移,没有人能轻易改变趋势。趋势包括两个…

    2022年8月22日
  • 这种神奇的红肉苹果给我锁住!姐妹抗老、去黄气就靠它了

    这种神奇的红肉苹果给我锁住!姐妹抗老、去黄气就靠它了! 女孩子们都梦想着自己有水嫩白皙的皮肤,俗话说“一白遮百丑”,皮肤好了,自然也可以拉高颜值。所以拥有一个比较健康的皮肤是很重要…

    2022年9月25日
  • 最浪漫的地方-法国

    法国是一个浪漫的国度,现在就让我们去认识一下它吧 1.法国是欧洲西部的国家,包括科西加等岛屿,面积为55万k 。 2.巴黎是世界上最繁华的大都市之一,每年有大量的人奔赴巴黎。有很多…

    2022年8月16日
  • 福建“重口味”美食之一,这个东西让人又怕又爱,现在很难见到

    每个地方都有属于自己的饮食文化,但福建总被误认为是“重口味”美食的集大成者,这道菜的出现更是让外地人的误解越发加深,这是为什么呢?我们一起往下看吧! 流蜞是什么 “流蜞”其实是方言…

    2022年8月26日
  • NBA5个堪称“神级”的交易:绿军探花秒变状元,独行侠一箭双雕

    前言: 跟赛场之上真刀真枪的比拼相比,球队在交易方面的博弈,堪称是没有硝烟的战场。各支球队的管理层每天都在挖空心思,想要通过各种交易谋求利益的最大化。 既然同样是一种比拼,那自然也…

    2022年8月17日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息