令人迷惑的隐藏(C++高手请进),分不够可以加

jmjunta 2006-04-19 06:22:54
各位大虾:
我是一名C++初学者,在学习C++的知识中碰到了一个令我不解的问题,请各位高手不吝赐教.
问题:C++中关于重载与覆盖的规则如下:
重载
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有 virtual 关键字。
现在有以下代码:
#include <iostream.h>
class Base
{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
void g(float x){ cout << "Base::g(float) " << x << endl; }
void h(float x){ cout << "Base::h(float) " << x << endl; }
};

class Derived : public Base
{
public:
virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
void g(int x){ cout << "Derived::g(int) " << x << endl; }
void h(float x){ cout << "Derived::h(float) " << x << endl; }
};


void main(void)
{
Derived d;
Base *pb = &d;
Derived *pd = &d;

pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3

}
调用结果是:
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3
我的问题是是:
对于函数g()到底是属于什么?(覆盖?重载?还是什么...)
这显然不是覆盖(因为覆盖必须满足:函数名相同,参数类型的个数相同),这里显然也不能说是重载,因为重载是相同的范围(在同一个类中);
如果说是:派生类继承了基类的函数,并于派生类中重载了此函数,但这应该不会引起继承来的那个函数被隐藏啊.
在下百思不得其解,请各位发表看法和高见.在线等待.
QQ:52372937
...全文
1121 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
justrun2005 2006-04-30
  • 打赏
  • 举报
回复
倒50mi大姐得了这么多分,请客啊
code_tin 2006-04-29
  • 打赏
  • 举报
回复
覆盖
override
准确点是隐藏
jackmtlee 2006-04-29
  • 打赏
  • 举报
回复
楼主也太无耻了吧,这是<<高质量程序设计语言C/C++>>林锐
上面的一个例子,林大师已经很清楚的描述了这个问题.
roger_77 2006-04-21
  • 打赏
  • 举报
回复
这样给分的??

jmjunta 2006-04-21
  • 打赏
  • 举报
回复
感谢各位参与此问题的讨论.让在下受益非浅.
xingzhao_m 2006-04-20
  • 打赏
  • 举报
回复
各是各 pb->向base类的g(),自然调用父类的函数
yumei20001 2006-04-20
  • 打赏
  • 举报
回复
这个例子好象是清华的那本C++教程的例子,在那本深入浅出MFC里也有相似的例子

Derived d;
Base *pb = &d;
Derived *pd = &d;

简单点理解:基类指针指向派生类的时候,调用的是基类的函数
派生类指针指向派生类的时候,调用的是派生类的函数

这个不是为了说明重载,因为函数g()并不是虚函数.
在MFC类库里有很多这种用法
Torch009 2006-04-20
  • 打赏
  • 举报
回复
看一下候Sir的C++对象模型。网上有电子的。
BOYGUARD110 2006-04-20
  • 打赏
  • 举报
回复
MARK
romanticlife 2006-04-20
  • 打赏
  • 举报
回复
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3
--------------------------------------
你也知道,定义的pd指向的是最近的g().
如果你要指向基类的g(),应该是这样的Base::g()
***
样主好像也有这样说的。
lovelinglijun1314 2006-04-20
  • 打赏
  • 举报
回复
胡说的多
gjianpro 2006-04-20
  • 打赏
  • 举报
回复
lz要苦练基本功了
toryhector 2006-04-20
  • 打赏
  • 举报
回复
我现在终于明白了一个道理,继承,多态听上去多么好。那都是理论分析设计用的,在应用中这种BUG会死人的,以后不用多态了
ls82930 2006-04-20
  • 打赏
  • 举报
回复
你的pb是指向基类的啊,即使把子类对象付给pb,pb->g(3.14f)还是调用的基类的,因为g()不是虚函数。
pd是指向子类的指针,当然调用的就是子类的g()了。
这也不是重载也不是覆盖。
rickerliang 2006-04-20
  • 打赏
  • 举报
回复
hide
roger_77 2006-04-20
  • 打赏
  • 举报
回复
class Derived : public Base


Derived d;
Base *pb = &d;
Derived *pd = &d;

pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3


主要就是中继承中,类成员的处理虚函数与函数重载及函数重写的关系吧。

缺省情况下,类的成员函数是非虚拟的(nonvirtual), 当一个成员函数为非虚拟的时候,
通过一个类对象(指针或引用)而被调用的该成员函数,就是该类对象的静态类型中定义的
成员函数。
Base中定义的g()函数并不是虚函数,也就是说,
pb指针调用的就是指针所声明的类型(基类)本身的成员函数,与指针所指向的对象无关。
所以下面这个结果毫无疑问:
pb->g(3.14f); // Base::g(float) 3.14

主要疑问的问题应该是出在另一个执行结果。
在C++Primer17.3节中写到:
C++语言初学者的一个常见的误解是,希望基类和派生类的成员函数构成一个重载函数
集.虽然基类的成员可以被直接访问,但是它们仍然属于基类的域.一个名字的重载候选函
数必须都出现在同一个域中。
也就是说,函数重载只能是在同个作用域内,
楼主所定义派生类的g()函数就隐藏了基类同名函数g()可视性。
所以,就有了
pd->g(3.14f); // Derived::g(int) 3
这个结果。

fiftymetre 2006-04-19
  • 打赏
  • 举报
回复
对Piboye(柳月清) 的回答,做一下补充吧,让他说的更易理解一点吧。


首先我们来看成员函数的查找

当调用一个成员函数的时候,分为三步的,第一:编译器查函数的名字,第二:从候选中选择最佳匹配函数

,(第二步的实现是有相当的难度的、//呵呵有一个关键的一点实参相依的查找 ADL 注1)第三:检查访问

核函数的权限。
下面来看一个关于函数查找的例子吧  嘻嘻

class aa {

public:
void you(double);
};

class bb : public aa {

void you(int);
};

......

bb b;

b.you(50.5);

----------------上面的代码调用的是那一个you呢?

第一:编译器查函数的名字。我们调用的是bb对象的成员对吧,所以从bb的作用域中查找,并定位到bb::you

上。


第二:从候选中选择最佳匹配函数。 所以理所当然的会去尝试匹配这个函数bb::you 。通过将实参50.5从

double转成了int来实现了这一点(精度就没有啦,转成了int型的50对吧)。

第三:检查访问核函数的权限。 当检查了这个函数的权限的时候发现了一个错误,因为bb::you为私有的。

(类默认为私有的)。这时情况就明了了吧。呵呵。类中的那一个看上去更好的匹配或是可以访问的函数you

已不在重要了。就因为在内层作用域中找到一个,编译器就不会到外层作用域去查找该名字了。而内层作用

域中的名名外层作用域中相同的名字。




注1:ADL(Argument Dependent Lookup)实参相依的查找。 它的使用是很直观的,大意为:当查找一个函

数调用表达式中的函数名字时,编译器也会到“包含函数调动实参的类型”的名字空间中检查的。
SammyLan 2006-04-19
  • 打赏
  • 举报
回复
这叫隐藏 (=_=)
100分给我吧
jmjunta 2006-04-19
  • 打赏
  • 举报
回复
请大家踊跃发言, 读君一长贴,胜读十年书.谢谢各位.
Dragon_augustine 2006-04-19
  • 打赏
  • 举报
回复
楼上的厉害!领教了
加载更多回复(21)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧