返回信息流这是一个Very Triky的问题...搞了一个多小时....万恶的函数式转型...jmpesp你真的搞的清楚么...
首先输出C是确定的,因为无论怎么转型, p都是指向一个C对象,而A、B中的fun都是虚函数,所以调用的肯定是C类方法
输出float看起来比较奇怪,原因是因为(B*)(A*)这个淫荡的、万恶的c-style转型
cout << (A*)p << endl;
cout << (B*)p << endl;
cout << (B*)(A*)p << endl;
得到以下输出:
00382E30
00382E34
00382E30
可见(B*)(A*)p 和 (A*)p是相同的
这是因为,C继承了A和B,所以一个C对象里包含了一个A对象和B对象。(A*)p使得p偏移到了C对象中的A对象, 接下来(B*)再对指向A对象的p进行转型,这时候问题就出现了,B对象并不包含A对象,编译器也不知道p指向的A对象实际上是包含在一个C对象里,所以(B*)这次转换,只是改变了p的静态类型,并没有改变p指向的位置,也就是说p还是指向一个A对象。所以通过p调用fun(1)的时候,查的是A的虚表,先查到virtual void A::fun(float),再到void C::fun(float)
这个问题的关键就在(B*)(A*)p这两个C-Style的函数式转型(functional cast)上:
(A*)p是从派生类C到基类A的转换,有可能是是个向上的static_cast,也有可能是个简单的reinterpret_cast, 从上面的分析结果上看(A*)是个static_cast的up cast,而由(A*)到(B*)的转换不可能是static_cast(static_cast<B*>(static_cast<A*>(p)))是编译不过的),所以只能是reinterpret_cast
这里又出现了一个问题,为什么(A*)p是个static_cast而不是reinterpret_cast?至少这与我的直觉不服,在ISO C++标准5.4节找到如下定义(见图)
也就是说一个C-style的强制类型转换如果可以解释成多个列表里的C++ style转型,取在列表里位置最前面的一个。static_cast在reinterpret_cast前,所以得到了下面的结果:
(B*)(A*)p 等价于 reinterpret_cast<B*>(static_cast<A*>(p))
由这道题目说明,千万不要用C-style对对象指针进行转型,请用C++-style的static_cast、reinterpret_cast和dynamic_cast
Over.
这是一条镜像帖。来源:北邮人论坛 / cpp / #34447同步于 2009/12/29
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
Re: 求大牛帮忙
jokerlee
2009/12/29镜像同步0 回复
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。