基类和派生类中定义了同名的(非虚)函数,指针会调用哪一个的问题

lpch06 2010-10-29 04:25:35
#include "iostream.h"
class A
{
public:
void fun(){ cout<<"This is A::fun()"<<endl;}
};
class B :public A
{
public:
void fun(){ cout<<"This is B::fun()"<<endl;}
};

void main(void)
{
A* pa;
B* pb= new B;
pa=pb;
pa->fun();
}

上段程序很简单。

书中说:“如果基类和派生类都定义了相同名称的成员函数(非虚),那么通过对象指针调用成员函数时,到底调用哪一个,必须视该指针的原始类型而定,而不是视指针实际所指向的对象的类型而定”。

如上程序中,虽然pa指向了B对象的一段内存,但是调用fun()函数时,调用的是A的函数(A::fun())。

反之:(类定义不变)
void main(void)
{
A* pa= new B;
B* pb;
pb=(B*)pa;
pb->fun();
}
输出是:B::fun()

这是为什么呢?(对于函数定义为虚函数时的情况我是了解的)类中的函数只是一段代码,那么,既然pa指向一段类B对象的区域,它又采取什么样的方式知道,自己需要调用A中定义的函数并执行其代码呢?

或者,在声明A* pa;时,pa中已经有了A中这个函数的信息还是怎样?迷糊~~
...全文
479 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
sstartFromZero 2012-12-17
  • 打赏
  • 举报
回复
我的理解是这样的,pB继承了pA,因此pB所指向的内存中有两个funC函数,当一个指针指向了该内存空间并调用funC函数时,是根据指针所定义的原始类型来确定是调用哪个funC函数的。不知道我这样理解对不对,求楼主解答。
wintersky2009 2010-10-29
  • 打赏
  • 举报
回复
走过,路过!!!
lpch06 2010-10-29
  • 打赏
  • 举报
回复
晕了。
----------------------------
哎~~只能这样了~~现在先记着,以后再慢慢了解吧~~谢谢各位~~
gomi 2010-10-29
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 lpch06 的回复:]

不知道这样理解对不对??
[/Quote]

晕了。
lpch06 2010-10-29
  • 打赏
  • 举报
回复
to:lthyxy

那就是不对咯~~我很想知道汇编层面发生了什么~~
liutengfeigo 2010-10-29
  • 打赏
  • 举报
回复
可以这么理解先。
lpch06 2010-10-29
  • 打赏
  • 举报
回复
不知道这样理解对不对??
lpch06 2010-10-29
  • 打赏
  • 举报
回复
to:gules gomi LightBoat09

想了想,是不是这样的一个原因呀~~可能不对,不过可以解释问题:

类A中声明void fun()时,暗加了一个this指针,在编译后实际上是:void fun((A*)this)

同理:

类B中声明void fun()时,暗加了一个this指针,在编译后实际上是:void fun((B*)this)

所以,两个函数的名称虽相同,但由于参数类型不同。所以实际上是两个函数。

这样,对于
void main(void)
{
A* pa;
B* pb= new B;
pa=pb;
pa->fun();
}

pa指向了一个B的对象,但是把它当做A的对象(比如,pa只能调用类A中声明的变量,不能调用类B声明但

类A中没有声明的成员变量)

所以,pa->fun();实际上是pa->fun((A*)pa);所以只能调用参数类型匹配的

void fun((A*)this),即A::fun()。


gomi 2010-10-29
  • 打赏
  • 举报
回复
没有特别原因,只是C++语言的规范而已,如果人们定义了另一套规范就是另一种规则了。

比较下面2种规则:
1、使用关键字virtual定义虚函数,调用虚函数时调用实际对象的函数
2、没有虚函数的的概念,增加一个“=>”操作符,当使用pointer=>function()时调用实际对象的函数

以上2种规则都可以满足开发的需要,但很显然第2种会让编译器变得复杂而且程序员更容易犯错误。

gules 2010-10-29
  • 打赏
  • 举报
回复
如果基类和派生类都定义了相同名称的成员函数(非虚),那么通过对象指针调用成员函数时,到底调用哪一个,必须视该指针的原始类型而定,而不是视指针实际所指向的对象的类型而定”。
--------------------------------------------------------------------------------
怎么这么复杂的解释?

只要记住:对于非虚的成员函数,就与动态绑定(多态)没关系,全部都是静态绑定!

另,自己写的类,最好不要override(改写)继承而来的非虚函数。
lpch06 2010-10-29
  • 打赏
  • 举报
回复
原因说简单也简单,因为你用的是B的指针去调用的

--------------------------------------------------

如果基类和派生类都定义了相同名称的成员函数(非虚),那么通过对象指针调用成员函数时,到底调用哪一个,必须视该指针的原始类型而定,而不是视指针实际所指向的对象的类型而定”。

上一段话很简单,看两遍就记住了,关键是我想知道原因,最好的情况当然是知其然知其所以然。所以,我想

弄明白~~
lpch06 2010-10-29
  • 打赏
  • 举报
回复
ls是不是说,在编译完成之后,pa指针就和类A中的fun函数联系起来了,所以它只能(只得)调用A::fun

()?那能不能讲一讲在汇编层面上所发生的事情?
ayw215 2010-10-29
  • 打赏
  • 举报
回复
原因说简单也简单,因为你用的是B的指针去调用的
小楫轻舟 2010-10-29
  • 打赏
  • 举报
回复
LZ开一下虚函数的原理,
静态联编和动态联编

65,179

社区成员

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

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