刚刚参考了一下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
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