
昵称:Jackal The Dire
等级:版主
文章:2096
积分:579
星座: 水瓶座 |
发信人: jokerlee (Jackal The Dire), 信区: CPP 标 题: Re: 求大牛帮忙 发信站: 北邮人论坛 (Wed Dec 30 05:04:06 2009), 站内 这是一个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. -- ※ 修改:·jokerlee 于 Dec 30 11:23:56 2009 修改本文·[FROM: 2001:da8:215:8206:4bc:6d3c:ef9c:*] ※ 来源:·北邮人论坛 http://forum.byr.edu.cn·[FROM: 2001:da8:215:8206:b8bc:d3c1:51f2:*] |
|