2010-06-14 12 views
5

En C# puede utilizar as para convertir un tipo u obtener nulo:Equivalente al comando C# 'as' en C++?

Object o = Whatever(); 
String s = o as String; 

¿Hay una manera fácil similar a lograr esto en C++?

Estoy usando Visual Studio 2010, si eso es importante.

[Actualizar]: recuerde, hay una diferencia muy importante entre la fundición y el uso de as. Casting (al menos en C#) lanzará una excepción si el tipo no coincide:

Object o = null; 
String s = (String)o; // Will crash. 
+0

Ninguna de las respuestas que sugieren el uso de 'dynamic_cast' son correctas. La palabra clave C# es una operación de conversión, pero 'dynamic_cast' es un elenco. –

+1

@Jon Dibling - 'como' es un elenco. solo tiene éxito si el elenco es válido. – sylvanaar

+0

@sylvanaar: de acuerdo con la especificación de C#, tanto el operador de conversión como la palabra clave 'as' realizan conversiones. Ver 7.9.11 y 7.6.6 –

Respuesta

9

En C++, esto sería un dynamic_cast, si tuviera una jerarquía donde Object es el padre y String es el secundario.

Object * p = createMyObject(); 
String * s = dynamic_cast<String *>(p); 
if(s) 
{ 
    ... 
} 

dinámico de fundición de un puntero devolverá un puntero al objeto si el yeso es posible, o un puntero nulo en caso contrario.

Además, la referencia de fundición dinámica devolverá una referencia al objeto si el molde es posible, o lanzará una excepción.

+4

Su sintaxis es incorrecta. debería ser: 'dynamic_cast (p);' y debería tener en cuenta que String debe derivarse de Object. –

+0

De hecho, agregué el puntero. –

+3

Como una extensión de lo que dijo Neil, no existe una clase base común de la que todas las clases en C++ derivan automáticamente. Algunas bibliotecas tienen una clase central, como Qt y wxWidgets, pero se derivan explícitamente de ellas, ya sea directamente o a través de otra clase. – blwy10

3

Uso dynamic_cast<type>(), pero sólo funcionará con los punteros, no objetos estáticos.

+4

Con los punteros, obtienes un puntero nulo si el lanzamiento no es válido. Funciona con referencias, pero arroja una excepción si no es válido. –

5

En C++ no existe una clase de objeto base, por lo que, en general, no hay forma de hacerlo. Sin embargo, puede hacerlo por jerarquías específicas:

struct A { 
    virtual ~A() {} 
}; 

struct B : public A { 
}; 

A * p = Something();  // Something() may return an A * or a B * 
B & b = dynamic_cast <B&>(*p); 

El reparto dinámico lanzará una excepción si p no apunta hacia algo que con seguridad se puede convertir en una referencia B.

+0

solo para confirmar, ¿podemos dynamic_cast en referencia? –

+0

@Dbger Sin duda podemos. –

+0

Debemos tener en cuenta las diferencias de una referencia a la fundición de un puntero. Si el dynamic_cast falla: en un puntero, se devuelve NULL; en una referencia se arroja una excepción –

2

Por lo que puedo leer en: C# Programmer's Reference: AS el operador as realiza la misma tarea que dynamic_cast en C++.

+1

No, definitivamente no es así. C# 'as' es una conversión. dynamic_cast es un elenco. –

+0

Teniendo en cuenta esto desde la referencia del programador C#: * El operador as es como un molde, excepto que arroja nulo el error de conversión en lugar de generar una excepción. * Y: 'expresión como tipo' es equivalente a:' ¿expresión es tipo? (tipo) expresión: (tipo) null'. Yo diría que el operador 'as' se asemeja más a' dynamic_cast' especialmente porque 'as' no puede realizar conversiones definidas por el usuario. –

+0

Entiendo esto, pero la pregunta es sobre una operación equivalente en C++, por lo que, aunque no es importante distinguir entre 'emitir' y 'convertir' en un lenguaje como C#, hay una gran diferencia en C++. Entonces es importante ser claro. Usted mismo dijo: "como si fuera un yeso", no "como * es * como un yeso". Y la especificación C# es igualmente explícita: (7.6.6): "Una expresión moldeada se usa para convertir explícitamente una expresión a un tipo dado" y (7.9.11): "El operador as se usa para convertir explícitamente un valor a un tipo de referencia dado o tipo anulable "Estas son conversiones, no conversiones. –

-1

En C# la palabra clave asconvierte un valor en otro tipo. Hay un código que admite esta conversión (probablemente en el tiempo de ejecución de C#). Esto no es un elenco.

En general, no se puede usar dynamic_cast o cualquier otro tipo de molde en C++ para lograr esto, porque los moldes y las conversiones no son lo mismo. Digo 'en su mayor parte' porque algunos tipos pueden ser convertidos usando static_cast, para convertir un int en un pero esto sigue siendo una conversión, no un reparto. Además, si ha introducido un sistema de tipo donde todo se deriva de una clase base Object que tiene esta funcionalidad de conversión, es posible que pueda construir un mecanismo para admitir esta conversión usando dynamic_cast, pero habría tenido que escribir este mecanismo y esto no parece ser lo que intentas hacer.

No hay nada incorporado en C++ que hará esta conversión por usted; en otras palabras, no hay C++ equivalente a la palabra clave C# as.

Si desea realizar esta conversión, a menudo se puede utilizar corrientes:

#include <sstream> 
#include <string> 
#include <iostream> 
using namespace std; 

int main() 
{ 
    float f = 42.0f; 
    stringstream ss; 
    ss << f; 
    string s = ss.str(); 
    cout << "Float: " << f << ", String '" << s << "'"; 

    return 0; 
} 

<sstream> es parte del estándar de C++, por lo que en este sentido debería tenerla en cuenta para estar 'en el idioma'.

Usar flujos para hacer esta conversión puede ser bastante torpe. Boost offerslexical_cast que puede ser utilizado para realizar estas conversiones sencillas con menos código:

#include <sstream> 
#include <iostream> 
#include <boost\lexical_cast.hpp> 

using namespace std; 

int main() 
{ 
    string s = "42"; 
    float f = boost::lexical_cast<float>(s); 

    cout << "Float: " << f << ", String '" << s << "'"; 

    return 0; 
} 
+0

¿Cuál es la diferencia entre la conversión y la conversión de un tipo de referencia en C#? – sylvanaar

+0

@sylvanaar: En C# parece que no existe tal cosa como un verdadero "molde" en el sentido C++. En C++, un molde significa "la variable fingida x es de tipo Y", pero de acuerdo con la especificación C#, (7.6.6) "Una expresión moldeada se usa para convertir explícitamente una expresión a un tipo dado". y (7.9.11) "El operador as se usa para convertir explícitamente un valor a un tipo de referencia o tipo anulable. A diferencia de una expresión de conversión (§7.6.6), el operador as nunca arroja una excepción. la conversión no es posible, el valor resultante es nulo." –

+0

@sylvanaar: Si rechazó mi respuesta, debe pensar que es incorrecta. ¿Qué, exactamente, está mal en mi publicación? –