虚函数 重载 覆盖 的问题。
lass A
{
public:
A()
{
cout<<"基类默认构造函数"<<endl ;
};
A(int i)
{
cout<<"基类参数构造"<<endl;
};
virtual int get()
{
m_i=8;
return m_i;
}
;
// mutable成员变量,即使在const方法里面也能被修改
mutable int m_i;
};
class B :public A
{
public:
B()
{
cout<<"派生类默认构造"<<endl ;
};
B::B(int i):A(i) //这么写就只会调用基类参数构造函数
{
// A::A(i);
// 如果把上面的A(i) 挪到这个地方,
// 那结果就是除了调用了基类的参数构造函数,还调用了基类的非构造函数
cout<<"派生类参数构造"<<endl ;
};
virtual int get()
{
m_i=9;
return m_i;
}
// mutable成员变量,即使在const方法里面也能被修改
// mutable int m_i;
};
B b;
A* pa=&b;
B* pb=&b;
int ma=pa->get();
int mb=pb->get();
请问 ma 和 mb 分别得几,如果把virtual 去掉呢?
问题点数:50、回复次数:16Top
1 楼gezihou(无名)回复于 2006-01-25 00:19:22 得分 0
ma应该是8,mb应该为9吧。去掉virtual,B中的get()函数应该不能再进行声明啦。Top
2 楼wd_6532(用frontpage写asp,jsp,php,ace)回复于 2006-01-25 00:24:40 得分 0
错
你试试。Top
3 楼gezihou(无名)回复于 2006-01-25 00:26:52 得分 5
应该是两个都为9吧,没注意前面的B b;A* pa=&b;Top
4 楼wd_6532(用frontpage写asp,jsp,php,ace)回复于 2006-01-25 00:46:50 得分 0
为什么都是9?
pa->get();应该是调用基类的函数阿,所以我觉得应该是8
可运行是9,为什么Top
5 楼gezihou(无名)回复于 2006-01-25 00:50:22 得分 0
虚函数将基类的函数覆盖啦,pa=&b;时保存的仍然是B的函数指针Top
6 楼wd_6532(用frontpage写asp,jsp,php,ace)回复于 2006-01-25 01:05:35 得分 0
完了,我又晕了。
那多态性是怎么回事来着,我记得按照多态性的规则就是按照当前指针的类型来判断调用哪个函数的。
pa->get(); pa是基类指针,应该调用基类的函数阿。
能不能帮忙举一下多态性的例子,要跟这个覆盖区别开来的,谢谢。Top
7 楼gezihou(无名)回复于 2006-01-25 01:24:27 得分 10
我推建一本书吧,侯捷译的《深度探索C++对象模型》这本书介绍的非常详细,从编译到实现说得非常详细。
多态是按照当前指针的类型来判断的,但是虚函数在编译的时候是保存在一个虚拟表(virtual table)中,这个表的指针保存在类的内存中,执行那个函数完全是看这个指针指向的位置(也就是实际的函数)。你的例子当中B b;在内存中保存的virtual table 指针是B的指针,虽经过pa=&b截断内存转换为基类A,但执行的函数仍然是通过B的virtual table 指针找到的函数。但是不是虚函数的就符合多态的规则啦。Top
8 楼gezihou(无名)回复于 2006-01-25 01:25:06 得分 0
不好意思,先查啦一下书Top
9 楼wd_6532(用frontpage写asp,jsp,php,ace)回复于 2006-01-25 01:46:48 得分 0
我上面是不是把多态性记错了?
多态性是可以用基类指针调用派生类的方法吧,而这正是利用虚函数和函数覆盖来实现的吧。Top
10 楼wd_6532(用frontpage写asp,jsp,php,ace)回复于 2006-01-25 02:00:50 得分 0
那多态性是怎么回事来着,我记得按照多态性的规则就是按照当前指针的类型来判断调用哪个函数的
====================
我上面是不是说错了,是不是应该这么说 多态不是按照指针类型来决定调用哪个函数的,而是根据指针指向的对象的类型来决定的。
多态是按照当前指针的类型来判断的
============
你是不是也被我带到沟里去了?
Top
11 楼Mackz(在相互)回复于 2006-01-25 08:57:40 得分 10
多态性的规则就是按照当前指针的类型
+++++
多态性应该是按照当前指针指向的对象的实际类型来调用虚拟成员函数的,也就是说,不管你的指针处于类层次的哪一级,总是调用实际的对象的成员函数,以上面为例:
B b;
A* pa=&b; //pa->get()调用的仍然是B::get(),即所谓虚函数表在起作用
B* pb=&b;
Top
12 楼xtaddqqug(王中)回复于 2006-01-25 09:17:47 得分 10
1、如果您以一个“基类的指针”如您所定义的pa指向“派生类的对象”如您所定的b,那么经由该指针您只能够调用基类所定义的函数。
2、如果您以一个“派生类的指针”指向一个“基类的对象”。您必须做显示的类型转换。
3、如果基类与派生类都定义了“同名的成员函数”,参照第一条。
4、但如同名函数是“虚拟函数”,则调用“指针所指的对象”的函数。因为为了实现动态聚束(后期聚束),每一个“内含虚拟函数的类”,编译器都会为生成一个虚拟函数表,表中的每一项记录都是一个函数指针,指向一个虚拟函数。
总结:
如是virtual,pa->get()=pa->vptr->get();ma=mb=9
如不是virtual,ma=8,mb=9;Top
13 楼yingpf(阿飛)回复于 2006-01-25 09:58:21 得分 5
楼主看看虚拟函数表Top
14 楼jslisong(碧螺春)回复于 2006-01-25 10:03:42 得分 5
这个是不是考试题目?
实际写程序一看就知道了。Top
15 楼wd_6532(用frontpage写asp,jsp,php,ace)回复于 2006-01-25 10:05:57 得分 0
每次学习不能真正心神领会,是我发展的瓶颈,也我初中学习方法的失败延至到今的后果.Top
16 楼shmily1280(锄禾)回复于 2006-01-25 13:36:46 得分 5
对,是你对多态的概念没有理解...
其实这种东西,要理解概念,然后再自己写段程序试试就记住了.
VC中的函数重写就是这样的...
Top




