dynamic_cast operator
converts the operand expression to an object of type Type-id.
Grammar
dynamic_cast < Type-id > (expression)
Note
Type-id must be a pointer or reference to a previously defined class type or "pointer to void". If Type-id is a pointer, the type of expression must be a pointer and the left value if Type-id is a reference.
See static_cast for a description of the differences between static and dynamic casts, and for the circumstances in which they are suitable for use.
There are two major changes in the behavior of dynamic_cast in managed code.
The dynamic_cast of the pointer to the underlying type of the boxed enumeration will fail at run time, returning 0 instead of the converted pointer.
Dynamic_cast will no longer throw an exception, and the conversion fails at run time when Type-id is an internal pointer to a value type. The conversion returns 0 indicating that the run value is not raised.
If Type-id is a pointer to a clear, accessible, direct or indirect base class that points to expression, the result is a pointer to the unique child object of the Type-id type. For example:
Dynamic_cast_1.cpp
//compile with:/C
class B {};
Class C:public B {};
Class D:public C {};
void f (d* PD) {
c* pc = dynamic_cast<c*> (PD); Ok:c is a direct base class
//PC points to C subobject of PD
b* PB = dynamic_cast<b*> (PD); Ok:b is a indirect base class
//PB points to B subobject of PD
}
This transformation type is called "convert up" because it will move the pointer on the class hierarchy from the derived class to the class derived from the class. An upward transition is an implicit conversion.
If Type-id is void*, the runtime checks to determine the actual type of expression. The result is a pointer to the complete object by expression. For example:
Dynamic_cast_2.cpp
//compile with:/c/gr
class A {virtual void F ();};
Class B {virtual void F ();};
void F () {
A * pa = new A;
b* PB = new B;
void* PV = dynamic_cast<void*> (PA);
PV now points to an object of type A
PV = dynamic_cast<void*> (pb);
PV now points to an object of type B
}
If Type-id is not void*, do a run-time check to determine if the object pointed to by expression can be converted to a type that is pointed by Type-id.
If the expression type is the base class for the Type-id type, do a run-time check to see if expression does point to the complete object of the Type-id type. If true, the result is a pointer to the complete object of the Type-id type. For example:
Dynamic_cast_3.cpp
//compile with:/c/gr
class B {virtual void F ();};
Class D:public B {virtual void F ();};
void F () {
b* PB = new D; Unclear but ok
b* pb2 = new B;
d* PD = dynamic_cast<d*> (pb); OK:PB actually points to a D
d* pd2 = dynamic_cast<d*> (PB2); PB2 points to a B not a D
}
This transformation type is called "downward conversion" because it will move the pointer under the class hierarchy from the given class to the class derived from the class.
For multiple inheritance, the possibility of introducing ambiguity. Consider the class hierarchy shown in the following illustration.
For CLR types, if the conversion can be performed implicitly, the dynamic_cast result is no-op, and if the conversion fails, the MSIL isinst instruction performs a dynamic check and returns NULLPTR.
The following example uses dynamic_cast to determine whether a class is an instance of a particular type:
Dynamic_cast_clr.cpp
//compile with:/clr
using namespace System;
void Printobjecttype (object^o) {
if (dynamic_cast<string^> (o))
Console::WriteLine ("Object is a String" );
else if (dynamic_cast<int^> (o))
Console::WriteLine ("Object is a int");
}
int main () {
object^o1 = "Hello";
Object^o2 = ten;
Printobjecttype (O1);
Printobjecttype (O2);
}
Show class hierarchies with multiple inheritance
Show class hierarchies for multiple inheritance
A pointer to a type D object can be safely cast to B or C. However, if D is coerced to a pointer to a object, which instance of a will result in a? This will result in an ambiguous cast error. To avoid this problem, you can perform two explicit transformations. For example:
Dynamic_cast_4.cpp
//compile with:/c/gr
class A {virtual void F ();};
Class B {virtual void F ();};
Class D:public B {virtual void F ();};
void F () {
d* pd = new D;
b* PB = dynamic_cast<b*> (PD); A
* PA2 = dynamic_cast<a*> (pb); Ok:unambiguous
}
When you use a virtual base class, other ambiguity problems are introduced. Consider the class hierarchy shown in the following illustration.
Show class hierarchies for virtual base classes
In this hierarchy, a is a virtual base class. For the definition of a virtual base class. Given an instance of class E and a pointer to a child object, the dynamic_cast pointing to the B pointer will fail in the ambiguity. You must first convert the cast back to the full E object, and then in a clear way, reverse the hierarchy and get to the correct B object.
Consider the class hierarchy shown in the following illustration.
Given an object of type E and a pointer to a D child object, navigate from the D child object to the leftmost a child object, and you can make three conversions. You can perform dynamic_cast conversions from the D pointer to the e pointer, and then perform the conversion (dynamic_cast or implicit conversions) from E to B, and finally perform an implicit conversion from B to A. For example:
Dynamic_cast_5.cpp
//compile with:/c/gr
class A {virtual void F ();};
Class B:public A {virtual void F ();};
Class C:public A {};
Class D {virtual void F ();};
Class E:public B, public C, public D {virtual void F ();
void f (d* PD) {
e* PE = dynamic_cast<e*> (PD);
b* PB = pe; Upcast, implicit conversion
* pa = PB; Upcast, implicit conversion
}
The dynamic_cast operator can also use the perform "reciprocal conversion". It is possible to use the same class hierarchy for pointer conversions, such as converting from a B child to a D child object, as long as the entire object is class-converted E.
Consider converting to each other, actually converting from pointer to D to the left of a child object as long as two steps. You can perform conversion from D to B, and then perform an implicit conversion from B to A. For example:
Dynamic_cast_6.cpp
//compile with:/c/gr
class A {virtual void F ();};
Class B:public A {virtual void F ();};
Class C:public A {};
Class D {virtual void F ();};
Class E:public B, public C, public D {virtual void F ();
void f (d* PD) {
b* PB = dynamic_cast<b*> (PD); Cross cast a
* pa = PB; Upcast, implicit conversion
}
Converts a null pointer value to a NULL pointer value of the target type by dynamic_cast.
When you use dynamic_cast < Type-id > (expression), if expression cannot be safely converted to type Type-id, Run-time checks can cause transformations to fail. For example:
Dynamic_cast_7.cpp
//compile with:/c/gr
class A {virtual void F ();};
Class B {virtual void F ();};
void F () {
A * pa = new A;
b* PB = dynamic_cast<b*> (PA); Fails at runtime, not safe;
B not derived from A
}
The value of the unqualified conversion of the pointer type is a null pointer. Unqualified conversions of reference types can throw bad_cast exceptions. If expression does not point to and does not reference a valid object, the __non_rtti_object exception is raised.
For an explanation of the exception __non_rtti_object, see typeID.
The following example creates a base class (structure a) pointer, which is an object (structure C). This and in this case is a virtual function that enables Run-time polymorphism.
The example also calls a non-virtual function in the hierarchy.
/dynamic_cast_8.cpp//compile with:/gr/ehsc #include <stdio.h> #include <io
stream> struct A {virtual void Test () {printf_s ("in a\n");
}
};
struct B:A {virtual void Test () {printf_s ("in b\n");
} void Test2 () {printf_s ("test2 in b\n");
}
};
struct C:B {virtual void Test () {printf_s ("in c\n");
} void Test2 () {printf_s ("test2 in c\n");
}
};
void Globaltest (a& a) {try {C &c = dynamic_cast<c&> (a);
printf_s ("in globaltest\n");
catch (Std::bad_cast) {printf_s ("Can ' t cast to c\n");
the int main () {A *pa = new C;
A *PA2 = new B;
Pa->test ();
B * PB = Dynamic_cast<b *> (PA);
if (Pb) Pb->test2 ();
C * pc = Dynamic_cast<c *> (PA2);
if (PC) Pc->test2 ();
C Constack;
Globaltest (Constack);
Would fail because B knows nothing about C B Bonstack;
Globaltest (Bonstack); }
Output:
In the C test2 in the
B in
globaltest
Static_cast operator
converts expression to Type-id, type, based only on the type that exists in the expression.
Grammar
Static_cast <type-id> (expression)
Note
in standard C + +, runtime type checking is not performed to help ensure the security of the conversion. In C++/cx, compile-time and run-time checks are performed.
The static_cast operator can be used to convert a pointer to a base class to an operation that points to a pointer to a derived class. This type of conversion is not always secure.
You typically use static_cast to convert numeric data types, such as converting an enum to an integral type or converting an integer to a floating-point type, and you can determine the type of data that participates in the transformation. static_cast conversion security is not as good as dynamic_cast conversion, because Static_cast does not perform run-time type checking, and dynamic_cast performs the check. The dynamic_cast of an ambiguous pointer will fail, and Static_cast's return result appears to be no problem, which is dangerous. Although dynamic_cast conversions are more secure, dynamic_cast only applies to pointers or references, and run-time type checking is also an overhead.
In the following example, because D may have fields and methods that are not in B, the row d* pd2 = static_cast<d*> (PB); Not safe. However, because D always contains all B, the row b* PB2 = static_cast<b*> (PD); is a safe conversion.
Static_cast_operator.cpp
//compile with:/ld
class B {};
Class D:public B {};
void F (b* pb, d* PD) {
d* pd2 = static_cast<d*> (pb); Not safe, D can have fields
//and methods which are not in B.
b* PB2 = static_cast<b*> (PD); Safe conversion, D always
//contains all of B.
}
Unlike dynamic_cast, PB static_cast conversions do not perform run-time checks. The objects pointed to by PB may not be object of type D, in which case it would be disastrous to use *PD2. For example, a member function that calls a class D (not a class B) might cause an access violation.
The dynamic_cast and static_cast operators can move pointers throughout the class hierarchy. However, static_cast is completely dependent on the information provided by the conversion statement and may not be secure. For example:
Static_cast_operator_2.cpp
//compile with:/ld/gr
class B {public
:
virtual void Test () {}
};
Class D:public B {};
void F (b* pb) {
d* PD1 = dynamic_cast<d*> (pb);
d* PD2 = static_cast<d*> (pb);
}
If PB does point to an object of type D, PD1 and PD2 will get the same value. If PB = = 0, they will also get the same value.
If the PB points to an object of type B, rather than to the complete class D, then dynamic_cast is sufficient to determine the return of zero. However, Static_cast relies on the programmer's assertion that PB points to the object of type D, and thus simply returns a pointer to that hypothetical D object.
Therefore, static_cast can perform implicit conversions in reverse, in which case the result is indeterminate. This requires the programmer to verify that the results of the static_cast conversion are secure.
This behavior also applies to types other than classes. For example, static_cast can be used to convert an int to char. However, the resulting char may not have enough bits to hold the entire int value. Again, this requires the programmer to verify that the results of the static_cast conversion are secure.
The static_cast operator can also be used to perform any implicit conversions, including standard conversions and user-defined conversions. For example:
Static_cast_operator_3.cpp
//compile with:/ld/gr
typedef unsigned char BYTE;
void F () {
char ch;
int i =;
float f = 2.5;
Double dbl;
ch = static_cast<char> (i); int to char
dbl = static_cast<double> (f); Float to double
i = static_cast<byte> (ch);
}
The
static_cast operator can explicitly convert an integer value to an enumeration type. If the integer value is not within the scope of the enumeration value, the resulting enumeration value is indeterminate. The
static_cast operator converts a null pointer value to a NULL pointer value of the destination type.
Any expression can be explicitly converted to a void type through the static_cast operator. The target void type can optionally contain a const, volatile, or __unaligned attribute. The
static_cast operator cannot convert a const, volatile, or __unaligned attribute.