dynamic_cast (Operador)dynamic_cast Operator

Convierte el operando expression en un objeto del tipo type-id.Converts the operand expression to an object of type type-id.

SintaxisSyntax

dynamic_cast < type-id > ( expression )

ObservacionesRemarks

type-id debe ser un puntero o una referencia a un tipo de clase definido previamente o un "puntero a void".The type-id must be a pointer or a reference to a previously defined class type or a "pointer to void". El tipo de expression debe ser un puntero si type-id es un puntero, o un valor L si type-id es una referencia.The type of expression must be a pointer if type-id is a pointer, or an l-value if type-id is a reference.

Vea static_cast para obtener una explicación de la diferencia entre las conversiones estáticas y dinámicas, y Cuándo es adecuado utilizar cada una de ellas.See static_cast for an explanation of the difference between static and dynamic casting conversions, and when it is appropriate to use each.

Hay dos cambios importantes en el comportamiento de dynamic_cast en código administrado:There are two breaking changes in the behavior of dynamic_cast in managed code:

  • dynamic_cast para un puntero al tipo subyacente de una enumeración con conversión Boxing se producirá un error en tiempo de ejecución, devolviendo 0 en lugar del puntero convertido.dynamic_cast to a pointer to the underlying type of a boxed enum will fail at runtime, returning 0 instead of the converted pointer.

  • dynamic_cast ya no producirá una excepción cuando type-id sea un puntero interior a un tipo de valor, con la conversión errónea en tiempo de ejecución.dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with the cast failing at runtime. La conversión devolverá ahora el valor de puntero 0 en lugar de producirse una excepción.The cast will now return the 0 pointer value instead of throwing.

Si type-id es un puntero a una clase base directa o indirecta accesible de forma no ambigua desde expression, el resultado es un puntero al subobjeto único de tipo type-id.If type-id is a pointer to an unambiguous accessible direct or indirect base class of expression, a pointer to the unique subobject of type type-id is the result. Por ejemplo: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 an indirect base class
                                   // pb points to B subobject of pd
}

Este tipo de conversión se denomina "conversión hacia arriba" porque sube un puntero en una jerarquía de clases, desde una clase derivada a una clase de la que se deriva.This type of conversion is called an "upcast" because it moves a pointer up a class hierarchy, from a derived class to a class it is derived from. Una conversión hacia arriba es una conversión implícita.An upcast is an implicit conversion.

Si type-id es void*, se realiza una comprobación en tiempo de ejecución para determinar el tipo real de expression.If type-id is void*, a run-time check is made to determine the actual type of expression. El resultado es un puntero al objeto completo al que apunta expression.The result is a pointer to the complete object pointed to by expression. Por ejemplo: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
}

Si type-id no es void*, se realiza una comprobación en tiempo de ejecución para ver si el objeto al que apunta expression se puede convertir al tipo indicado por type-id.If type-id is not void*, a run-time check is made to see if the object pointed to by expression can be converted to the type pointed to by type-id.

Si el tipo de expression es una clase base del tipo de type-id, se realiza una comprobación en tiempo de ejecución para ver si expression apunta realmente a un objeto completo del tipo de type-id.If the type of expression is a base class of the type of type-id, a run-time check is made to see if expression actually points to a complete object of the type of type-id. Si es cierto, el resultado es un puntero a un objeto completo del tipo de type-id.If this is true, the result is a pointer to a complete object of the type of type-id. Por ejemplo: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
}

Este tipo de conversión se denomina "conversión hacia abajo" porque baja un puntero en una jerarquía de clases, desde una clase especificada a una clase derivada de ella.This type of conversion is called a "downcast" because it moves a pointer down a class hierarchy, from a given class to a class derived from it.

En los casos de herencia múltiple, se introducen posibilidades de ambigüedad.In cases of multiple inheritance, possibilities for ambiguity are introduced. Considere la jerarquía de clases que se muestra en la ilustración siguiente.Consider the class hierarchy shown in the following figure.

Para los tipos CLR, dynamic_cast da como resultado una operación no operativa si la conversión se puede realizar implícitamente, o una isinst instrucción MSIL, que realiza una comprobación dinámica y devuelve nullptr si se produce un error en la conversión.For CLR types, dynamic_cast results in either a no-op if the conversion can be performed implicitly, or an MSIL isinst instruction, which performs a dynamic check and returns nullptr if the conversion fails.

En el ejemplo siguiente dynamic_cast se utiliza para determinar si una clase es una instancia de un tipo determinado:The following sample uses dynamic_cast to determine if a class is an instance of 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 an int");
}

int main() {
   Object^o1 = "hello";
   Object^o2 = 10;

   PrintObjectType(o1);
   PrintObjectType(o2);
}

Jerarquía de clases que muestra herencia múltipleClass hierarchy that shows multiple inheritance
Jerarquía de clases que muestra herencia múltipleClass hierarchy that shows multiple inheritance

Un puntero a un objeto de tipo D se puede convertir de manera segura a B o a C.A pointer to an object of type D can be safely cast to B or C. Sin embargo, si D se convierte para que apunte a un objeto A, ¿qué instancia de A resultaría?However, if D is cast to point to an A object, which instance of A would result? Esto produciría un error de conversión ambigua.This would result in an ambiguous casting error. Para eludir este problema, puede realizar dos conversiones no ambiguas.To get around this problem, you can perform two unambiguous casts. Por ejemplo:For example:

// dynamic_cast_4.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A {virtual void f();};
class D : public B, public C {virtual void f();};

void f() {
   D* pd = new D;
   A* pa = dynamic_cast<A*>(pd);   // C4540, ambiguous cast fails at runtime
   B* pb = dynamic_cast<B*>(pd);   // first cast to B
   A* pa2 = dynamic_cast<A*>(pb);   // ok: unambiguous
}

Se pueden introducir más ambigüedades cuando se utilizan clases base virtuales.Further ambiguities can be introduced when you use virtual base classes. Considere la jerarquía de clases que se muestra en la ilustración siguiente.Consider the class hierarchy shown in the following figure.

Jerarquía de clases que muestra clases base virtualesClass hierarchy that shows virtual base classes
Jerarquía de clases que muestra clases base virtualesClass hierarchy that shows virtual base classes

En esta jerarquía, A es una clase base virtual.In this hierarchy, A is a virtual base class. Dada una instancia de E la clase y un puntero al A subobjeto, dynamic_cast se producirá un error en un a un puntero a, B debido a la ambigüedad.Given an instance of class E and a pointer to the A subobject, a dynamic_cast to a pointer to B will fail due to ambiguity. Primero debe convertir de nuevo al objeto E completo y después volver a subir por la jerarquía, de forma no ambigua, hasta llegar al objeto B correcto.You must first cast back to the complete E object, then work your way back up the hierarchy, in an unambiguous manner, to reach the correct B object.

Considere la jerarquía de clases que se muestra en la ilustración siguiente.Consider the class hierarchy shown in the following figure.

Jerarquía de clases que muestra clases base duplicadasClass hierarchy that shows duplicate base classes
Jerarquía de clases que muestra clases base duplicadasClass hierarchy that shows duplicate base classes

Dado un objeto de tipo E y un puntero al subobjeto D, para navegar desde el subobjeto D hasta el subobjeto A situado más a la izquierda, se pueden realizar tres conversiones.Given an object of type E and a pointer to the D subobject, to navigate from the D subobject to the left-most A subobject, three conversions can be made. Puede realizar una dynamic_cast conversión del D puntero a un E puntero, una conversión ( dynamic_cast o una conversión implícita) de E a B y, por último, una conversión implícita de B a A .You can perform a dynamic_cast conversion from the D pointer to an E pointer, then a conversion (either dynamic_cast or an implicit conversion) from E to B, and finally an implicit conversion from B to A. Por ejemplo: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
   A* pa = pb;   // upcast, implicit conversion
}

El dynamic_cast operador también se puede usar para realizar una "conversión cruzada".The dynamic_cast operator can also be used to perform a "cross cast." Utilizando la misma jerarquía de clases, es posible convertir un puntero (por ejemplo, del subobjeto B al subobjeto D) siempre y cuando el objeto completo sea de tipo E.Using the same class hierarchy, it is possible to cast a pointer, for example, from the B subobject to the D subobject, as long as the complete object is of type E.

Teniendo en cuenta las conversiones cruzadas, en realidad es posible efectuar la conversión de un puntero a D a un puntero al subobjeto A situado más a la izquierda en solo dos pasos.Considering cross casts, it is actually possible to do the conversion from a pointer to D to a pointer to the left-most A subobject in just two steps. Puede realizar una conversión cruzada de D a B y después una conversión implícita de B a A.You can perform a cross cast from D to B, then an implicit conversion from B to A. Por ejemplo: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
}

Un valor de puntero NULL se convierte en el valor de puntero nulo del tipo de destino mediante dynamic_cast .A null pointer value is converted to the null pointer value of the destination type by dynamic_cast.

Cuando se utiliza dynamic_cast < type-id > ( expression ), si expression no se puede convertir de forma segura al tipo type-id, la comprobación en tiempo de ejecución hace que se produzca un error en la conversión.When you use dynamic_cast < type-id > ( expression ), if expression cannot be safely converted to type type-id, the run-time check causes the cast to fail. Por ejemplo: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
}

El valor de una conversión con errores al tipo de puntero es el puntero NULL.The value of a failed cast to pointer type is the null pointer. Un error de conversión al tipo de referencia produce una excepción bad_cast.A failed cast to reference type throws a bad_cast Exception. Si no expression señala ni hace referencia a un objeto válido, __non_rtti_object se produce una excepción.If expression does not point to or reference a valid object, a __non_rtti_object exception is thrown.

Vea typeid para obtener una explicación de la __non_rtti_object excepción.See typeid for an explanation of the __non_rtti_object exception.

EjemploExample

En el ejemplo siguiente se crea el puntero de la clase base (struct A) a un objeto (struct C).The following sample creates the base class (struct A) pointer, to an object (struct C). Esto, además del hecho de que hay funciones virtuales, hace posible el polimorfismo en tiempo de ejecución.This, plus the fact there are virtual functions, enables runtime polymorphism.

En el ejemplo también se llama a una función no virtual de la jerarquía.The sample also calls a non-virtual function in the hierarchy.

// dynamic_cast_8.cpp
// compile with: /GR /EHsc
#include <stdio.h>
#include <iostream>

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");
    }
}

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);

   // will fail because B knows nothing about C
    B BonStack;
    Globaltest(BonStack);
}
in C
test2 in B
in GlobalTest
Can't cast to C

Consulte tambiénSee also

Operadores de conversiónCasting Operators
Palabras claveKeywords