| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 5451 人关注过本帖, 2 人收藏
标题:[原创]C++中的指针(一) 简单指针
只看楼主 加入收藏
michaelsoft
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2006-7-13
收藏
得分:0 
刚刚参考了一下bs的tcpl特别版:

dynamic_cast<T*>(p)

looks at the object pointed to by p (if any). If that object is of class T or has a unique base class of
type T, then dynamic_  cast returns a pointer of type T* to that object; otherwise, 0 is returned. If
the value of p is 0, dynamic_cast<T*>(p) returns 0.

A dynamic_cast requires a pointer or a reference to a polymorphic type to do a downcast or a
crosscast.

to myajax95:
从A*转换到A*,根本不需要在运行时,因为两个类型一样,直接把值赋过去就行,如:
A* p1=(A*)0x1;
A* p2=dynamic_cast<A*>(p1);
如果有运行时动作的话,肯定会产生access violation错误,但是实际没有。从反汇编可以看出来:
         A* p1=(A*)0x1;
00411A2E  mov         dword ptr [p1],1
    A* p2=dynamic_cast<A*>(p1);
00411A35  mov         eax,dword ptr [p1]
00411A38  mov         dword ptr [p2],eax

to woodhead:
只有向下类型转换的时候才会要求被转换者必须是多态类(至少有一个虚函数)。如果是向上类型转换,编译时就可确定,是用不着运行时判断的,如:
class A{};
class B : public A {};

B b;
A* pa=dynamic_cast<A*>(&b);
反汇编:
         B b;
    A* pa=dynamic_cast<A*>(&b);
00411A2E  lea         eax,[b]
00411A31  mov         dword ptr [pa],eax

to all:
运行时转换(借助于vtable)只会发生在向下类型转换时,如:
class A{};
class B : public A {};

A a;
B* pb=dynamic_cast<B*>(&a);

由于借助了vtable,所以会要求A必须是多态类型,所以上述例子会编译失败。
而运行时的访问违规也只会发生在向下类型转换时,比如:
class A{ public: virtual~A() {} };
class B : public A {};

A* pa=(A*)0x1;
B* pb=dynamic_cast<B*>(pa);
反汇编:
         A* pa=(A*)0x1;
0041B1BE  mov         dword ptr [pa],1
    B* pb=dynamic_cast<B*>(pa);
0041B1C5  push        0   
0041B1C7  push        offset B `RTTI Type Descriptor' (455FB4h)
0041B1CC  push        offset A `RTTI Type Descriptor' (455FA0h)
0041B1D1  push        0   
0041B1D3  mov         eax,dword ptr [pa]
0041B1D6  push        eax  
0041B1D7  call        @ILT+3985(___RTDynamicCast) (419F96h)
0041B1DC  add         esp,14h
0041B1DF  mov         dword ptr [pb],eax

2006-07-31 13:20
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
明明是有access violation呀。家里没有VC2003,明天去公司试一下。
dynamic_cast不只看A*,而会继续查p1的info。


http://myajax95./
2006-07-31 13:52
woodhead
Rank: 3Rank: 3
等 级:新手上路
威 望:9
帖 子:1124
专家分:0
注 册:2005-7-18
收藏
得分:0 
咱的说法确实有问题

引一段

Dynamic cast

1 The result of the expression dynamic_cast<T>(v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or “pointer to cv void”. Types shall not be defined in a dynamic_cast. The dynamic_cast operator shall not cast away constness (5.2.11).

2 If T is a pointer type, v shall be an rvalue of a pointer to complete class type, and the result is an rvalue of type T. If T is a reference type, v shall be an lvalue of a complete class type, and the result is an lvalue of the type referred to by T.

3 If the type of v is the same as the required result type (which, for convenience, will be called R in this description), or it is the same as R except that the class object type in R is more cvqualified than the class object type in v, the result is v (converted if necessary).

4 If the value of v is a null pointer value in the pointer case, the result is the null pointer value of type R.

5 If T is “pointer to cv1 B” and v has type “pointer to cv2 D” such that B is a base class of D, the result is a pointer to the unique B subobject of the D object pointed to by v. Similarly, if T is “reference to cv1 B” and v has type “cv2 D” such that B is a base class of D, the result is an lvalue for the unique B subobject of the D object referred to by v. In both the pointer and reference cases, cv1 shall be the same cvqualification as, or greater cvqualification than, cv2, and B shall be an accessible unambiguous base class of D.

[Example:
struct B {};
struct D : B {};
void foo(D* dp)
{
B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;
}
—end example]

6 Otherwise, v shall be a pointer to or an lvalue of a polymorphic type .

7 If T is “pointer to cv void,” then the result is a pointer to the most derived object pointed to by v. Otherwise, a runtime check is applied to see if the object pointed or referred to by v can be converted to the type pointed or referred to by T.

8 The runtime check logically executes as follows:
— If, in the most derived object pointed (referred) to by v, v points (refers) to a public base class subobject of a T object, and if only one object of type T is derived from the subobject pointed (referred) to by v, the result is a pointer (an lvalue referring) to that T object.
— Otherwise, if v points (refers) to a public base class subobject of the most derived object, and the type of the most derived object has an unambiguous public base class of type T, the result is a pointer (an lvalue referring) to the T subobject of the most derived object.
— Otherwise, the runtime check fails.

9 The value of a failed cast to pointer type is the null pointer value of the required result type. A failed cast to reference type throws bad_cast (18.5.2).


[Example:
class A { virtual void f(); };
class B { virtual void g(); };
class D : public virtual A, private B {};
void g()
{
D d;
B* bp = (B*)&d; // cast needed to break protection
A* ap = &d; // public derivation, no cast needed
D& dr = dynamic_cast<D&>(*bp); // fails
ap = dynamic_cast<A*>(bp); // fails
bp = dynamic_cast<B*>(ap); // fails
ap = dynamic_cast<A*>(&d); // succeeds
bp = dynamic_cast<B*>(&d); // fails
}
class E : public D, public B {};
class F : public E, public D {};
void h()
{
F f;
A* ap = &f; // succeeds: finds unique A
D* dp = dynamic_cast<D*>(ap); // fails: yields 0
// f has two D subobjects
E* ep = (E*)ap; // illformed:
// cast from virtual base
E* ep1 = dynamic_cast<E*>(ap); // succeeds
}
—end example]

[此贴子已经被作者于2006-7-31 14:16:38编辑过]


2006-07-31 14:14
michaelsoft
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2006-7-13
收藏
得分:0 
vc6下是不是A必须是多态类才能编译通过啊?

2006-07-31 14:18
michaelsoft
Rank: 1
等 级:新手上路
帖 子:75
专家分:0
注 册:2006-7-13
收藏
得分:0 
我公司没有vc6,家里有,试了一下,在vc6里,尽管不是向下类型转换,也要求是多态类。看样子它对标准c++的支持还是不够。所以有没有访问违规出现的可能,还得看编译的时候要不要求是多态类,也就是依不依赖vtable了。

2006-08-01 08:32
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
用VC2003运行了一下,结果果然不crash。我再好好研究一下。

http://myajax95./
2006-08-01 09:00
lj_860603
Rank: 3Rank: 3
等 级:新手上路
威 望:6
帖 子:714
专家分:0
注 册:2006-1-25
收藏
得分:0 
95,偶来帮你顶!

我的原则很简单:不做不喜欢的事!
2006-08-02 11:12
xinhang
Rank: 2
等 级:论坛游民
帖 子:40
专家分:57
注 册:2006-7-25
收藏
得分:0 
顶上去! 以后再看!

\" ﹏╭⌒╮¤ ﹋ ^^
2006-08-03 01:01
pulf
Rank: 1
等 级:新手上路
帖 子:78
专家分:0
注 册:2006-7-31
收藏
得分:0 
收藏了。

2006-08-07 21:01
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 

查了一下ISO C++ standard 98 版和MSDN。懂了一些VC不同版本的问题,更新了顶楼的文章,大家有时间探讨一下。

[此贴子已经被作者于2006-8-19 7:15:35编辑过]


http://myajax95./
2006-08-18 13:36
快速回复:[原创]C++中的指针(一) 简单指针
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.015837 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved