免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2961 | 回复: 7
打印 上一主题 下一主题

[C++] [结贴]C++为什么要有"继承类函数隐藏"这种特性? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-03-28 18:27 |只看该作者 |倒序浏览
本帖最后由 werewq8q 于 2014-03-31 09:21 编辑

如下所示的代码,编译不过:

  1. #include<stdio.h>
  2. struct A{
  3.     void f(int){printf("A\n");}
  4. };
  5. struct B{
  6.     void f(){printf("B\n");}
  7. };
  8. struct C:A, B{
  9.     void f(){printf("C\n");}
  10. };
  11. int main(void){
  12.     C obj;
  13.     obj.f(1);
  14.     return 0;
  15. }
复制代码
错误是在f(1)这一行。看了下往上的解释说,继承类如果有同名的函数但是函数参数不同,就会自动隐藏基类的同名函数。
我觉得C++的这个规定怎么看起来是多次一举呢? 既然函数重载就是为了方便使用同一个函数名+不同的参数,为什么在继承的时候,子类不能"重载"父类的函数?

是不是说会造成编译的一些二义性还是什么? C++标准有没有章节对此规定或者做出解释?

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
2 [报告]
发表于 2014-03-28 19:20 |只看该作者
这么神奇?
试了一个果然不行,
只好用:
  1. #include<stdio.h>
  2. struct A{
  3.     void f(int){printf("A\n");}
  4. };
  5. struct B{
  6.     void f(){printf("B\n");}
  7. };
  8. struct C:A, B{
  9.     void f(){printf("C\n");}
  10. };
  11. int main(void){
  12.     C obj;
  13.         obj.A::f(1);
  14.     return 0;
  15. }
复制代码
了,
这个只能说C++不好了,
因为的确没有什么理由。

论坛徽章:
0
3 [报告]
发表于 2014-03-28 19:35 |只看该作者
不知道楼主想说什么,我按照你的意思自己写了下:
#include <iostream>

using namespace std;

class A{
public:
void f(int ){cout<<"A"<<endl;}
};

class B{
public:
void f(){cout<<"B"<<endl;}
};

class C:public A,B{
public:
void f(){cout<<"C"<<endl;}
};


int main()
{
        C obj;
        obj.f();
        return 0;
}

编译是没有问题的

论坛徽章:
0
4 [报告]
发表于 2014-03-28 19:38 |只看该作者
看错了。。。不好意思~

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
5 [报告]
发表于 2014-03-28 19:59 |只看该作者
正解是这样:
struct C:A, B{
    using A::f;
    void f(){printf("C\n");}
};


至于原始问题“为什么要有这种特性”。 是否存在准确原因我不记得了。
也许是名字查找是按层级来的,当前层级如果没有就去上一层级,而如果有就不会。
也许有其他更微妙的原因,可能会在“the design and evolution of c++”里有提。
也有可能这仅仅是设计时的二选一: a) 在当前层级有这个名字时不继续向上查找,除非显式地使用using。 b) 在当前层级有这个名字时依然继续向上查找, 除非显式地使用hiding(平行宇宙里的C++可能会是这样)。

因为一些设计选择与自己预想不符合就认为不好是不是太自负与幼稚了?

论坛徽章:
0
6 [报告]
发表于 2014-03-31 09:21 |只看该作者
OwnWaterloo 发表于 2014-03-28 19:59
正解是这样:


我非常欣赏你关于平行宇宙的解释。结贴!

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
7 [报告]
发表于 2014-03-31 10:17 |只看该作者
我个人认为这个或许是为设计逻辑方面考虑的。如果一个父类有某个函数dothing1但没有任何参数,而它的子类也有同名的doting1,但有一个int type这样的参数。现在我们讨论下为什么要这么设计:
1、如果这两个dothing1做的不是同一件事情,那么为什么不让子类的叫dothing2,也叫做dothing1不是很奇怪吗?
2、如果这两个做的是同一件事情,只是子类的做了额外的扩展,而且父类还有用,那么不如让子类叫dothing1Ex,不是更好吗?
3、通常来说,如果两个做的同一件事,完全可以根据参数再在子类调用父类的函数(比如type是0的时候子类dothing1转而调用父类的dothing1),也就是说一般情况下只要有子类的这个同名函数,已经完全可以胜任了。
4、如果真的有很特殊的设计需求,那么用using关键字吧。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
8 [报告]
发表于 2014-04-01 09:30 |只看该作者
重新想了下,可以换一个角度来看。

并不是派生类发现基类有一个f函数并想在其基础上添加一些重载:

  1. struct B
  2. {
  3.       virtual void f();
  4. };
复制代码
而是想实现另一个功能,假设叫g:

  1. struct D : B
  2. {
  3.       void g(long x);
  4. };
复制代码
这时候D::g没问题:

  1. int main()
  2. {
  3.       D().g(0);
  4. }
复制代码
一段时间之后,B的作者 —— 很有可能并不是D的作者并且完全不知道D的存在 —— 打算为B增加一项功能,并且不幸地也选用了g这个名字:

  1. struct B
  2. {
  3.       virtual void f();
  4.       void g(void* x);
  5. };
复制代码
目前世界里的D的作者就有一个机会考虑:B增加了一个功能? 和我原本用的名字冲突了? 我是否应该将它引入到自己的作用域里?
然后再考虑是否using。

而在一个C++总是会往上级查找名字的平行世界里,D以及使用D的代码马上就会遭殃。因为D().g(0)的候选有void B::g(void*)与void D::g(long int)。
考虑到有许多喜欢堆砌继承关系的OO狂热者,这种冲突是很容易出现的。 并且没有拒绝的using的机会。

不过那个世界里的C++里也许会有相应的hiding关键字 —— 也许那个世界里的BS并不在意往C++里引入过多的关键字 —— 以及对应的best practice:实现成员函数时总是先考虑hiding基类对应成员。

总之,可以换一个角度。不是派生类盯着基类有什么,而是派生类盯着基类没什么。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP