Traducción al español de RFOG
Un breve vistazo a la nueva sintaxis del C++/CLI y cómo mejora la vieja del MC++.
Cuando Microsoft presentó las Extensiones Administradas de C++ con VS.NET 7, los programadores de C++ las aceptaron con variadas reacciones. Mientras que mucha gente se mostró contenta de poder seguir utilizando C++, la gran mayoría se mostró insatisfecha con la sintaxis tan fea y distorsionada que definía al C++ Administrado. Obviamente, Microsoft se tomó la reacción con mucha seriedad y decidió que la sintaxis del MC++ no iba a triunfar mucho.
El 6 de octubre de 2003, ECMA anunció la creación de un nuevo grupo para supervisar el desarrollo de una serie de extensiones para enlazar el estándar ISO del lenguaje de programación C++ con la Infraestructura de Lenguajes Comunes (CLI), lo que llevó a que a estas extensiones fueran conocidas como el estándar C++/CLI, que será soportado por el compilador VC++ desde la salida de Whidbey (VS.NET 2005).
using namespace System; void _tmain() { Console::WriteLine("Hello World"); }
Bueno, realmente no parece muy diferente de la vieja sintaxis, salvo que no es necesario realizar una referencia a mscorlib.dll, dado que el compilador de Whidbey lo referencia implícitamente siempre que se compile con /clr (lo que ahora implica por defecto /clr:newSyntax).
Una de las principales confusiones en la antigua sintaxis consistía en el uso del * tanto con punteros no administrados como con referencias administradas. En C++/CLI Microsoft introduce el concepto de manejadores (handles).
void _tmain() { //El signo de puntuación ^ representa un handle String^ str = "Hello World"; Console::WriteLine(str); }
El signo de puntuación ^ (pronunciado como “tejado” –y reto a quien quiera a darle un nombre mejor. Nota del Traductor) representa un handle a un objeto manejado. De acuerdo con la especificación de CLI, un handle es una referencia a un objeto manejado. Los handles en la nueva sintaxis son los equivalentes a los punteros tipo __gc de la sintaxis MC++. Ahora, los handles ya no se confunden con los punteros y son asímismo de naturaleza totalmente diferente.
void _tmain() { String^ str = gcnew String("Hello World"); Object^ o1 = gcnew Object(); Console::WriteLine(str); }
La palabra reservada gcnew se utiliza para instanciar elementos CLR y devuelve un handle al objeto instanciado en el montículo CLR. La ventaja acerca de gcnew consiste en que permite diferenciar muy fácilmente entre las instancias administradas de las que no lo son.
Básicamente, lo único necesario para acceder a la BCL es la palabra reservada gcnew y el operador ^.
Los tipos CLR tienen un prefijo como adjetivo que describe la clase del tipo que es. Los siguientes son ejemplos de declaraciones en C++/CLI:
using namespace System; interface class IDog { void Bark(); }; ref class Dog : IDog { public: void Bark() { Console::WriteLine("Bow wow wow"); } }; void _tmain() { Dog^ d = gcnew Dog(); d->Bark(); }
Aquí, la sintaxis queda mucho más clara y fácil de ver que la antigua, en la que el código estaba constelado con palabras reservadas con doble subrayado como __gc e __interface.
Boxing es ahora implícito (¡bien!) y seguro respecto a tipos. Se realiza una copia bit a bit al crear un nuevo Object en el montículo CLR. Unboxing también es implicito - simplemente hay que realizar un reinterpret_cast y después desreferenciar.
void _tmain() { int z = 44; Object^ o = z; //boxing implícito int y = *reinterpret_cast<int^>(o); //unboxing Console::WriteLine("{0} {1} {2}",o,z,y); z = 66; Console::WriteLine("{0} {1} {2}",o,z,y); } // Salida // 44 44 44 // 44 66 44
El Object o es una copia boxed y no se refiere al tipo por valor int, lo que resulta obvio de la salida del segundo Console::WriteLine.
Cuando se encaja (box) un tipo por valor, el objeto devuelto mantiene el valor del tipo original.
void _tmain() { int z = 44; float f = 33.567; Object^ o1 = z; Object^ o2 = f; Console::WriteLine(o1->GetType()); Console::WriteLine(o2->GetType()); } // Salida // System.Int32 // System.Single
Por lo tanto, no se puede intentar desencajar (unbox) a un tipo diferente.
void _tmain() { int z = 44; float f = 33.567; Object^ o1 = z; Object^ o2 = f; int y = *reinterpret_cast<int^>(o2);//System.InvalidCastException float g = *reinterpret_cast<float^>(o1);//System.InvalidCastException }
Si se intenta, se obtiene una excepción del tipo System.InvalidCastException, ¡lo que nos demuestra la perfección en lo que respecta a la seguridad de tipos! Si se mira el código IL generado, se podrá observar a la instrucción MSIL box en acción. Por ejemplo:
void Box2() { float y=45; Object^ o1 = y; }
compila a:
.maxstack 1 .locals (float32 V_0, object V_1) ldnull stloc.1 ldc.r4 45. stloc.0 ldloc.0 box [mscorlib]System.Single stloc.1 ret
De acuerdo con la documentación sobre MSIL, “La instrucción box convierte el valueType bruto (un valor unboxed) en una instancia del tipo Object (del tipo O). Esto viene acompañado por la creación de un objeto nuevo y la copia de los datos de valueType al nuevo objeto asignado.”
Bueno, ¿quién querría utilizar el C++/CLI si puede usar C#, J# y ese VB como se llame para escribir código .NET? Aquí hay cuatro razones que di en el DevCon 2003 de Trivandrum (Dic 2003).
Nish es un tipo simpático que reside en Trivandrum, India, y que ha estado programando desde 1990, cuando tenía 13 años. Ha sido evangelista de varias tecnologías de Microsoft, como VC++, C++/CLI y el .NET Framework, por lo que está muy sorprendido de que Microsoft no le haya ofrecido el puesto de Jefe Evangelista en Redmond.
Trabaja para The Code Project y mantiene los productos de Dundas Ultimate Toolbox, Ultimate Grid y Ultimate TCP/IP que únicamente se venden en la tienda online de The Code Project. Suele frecuentar los foros de discusión de CP cuando no está programando, leyendo o escribiendo. Le gustaría visitar al menos tres docenas de países antes de que su mecanismo biológico humano deje de funcionar (eufemismo para evitar el uso de la palabra m.), y lamenta no haber visto la nieve hasta ahora. Y hay que mencionar que Nish no es muy dado a hablar sobre sí mismo.
Nish ha sido Microsoft Visual C++ MVP desde octubre de 2002. Mantiene un site sobre trucos y curiosidades de MVP en www.voidnish.com, donde se puede encontrar la lista consolidada de sus artículos, escritos e ideas sobre VC++, MFC, .NET y C++/CLI. Oh, también podrías querer echarle un vistazo a su blog sobre C++/CLI, MFC, .NET y otras muchas cosas en blog.voidnish.com
A Nish le encanta leer ciencia ficción, P. G. Wodehouse y Agatha Christie, y se imagina que es un escritor decente. Es autor de una comedia romántica, Summer Love and Some more Cricket y de un libro sobre programación, Extending MFC applications with the .NET Framework.
Pulsa aquí para ver el perfil público de Nishant Sivakumar.
El traductor es un programador de hardware embebido, le gusta la ciencia ficción (aunque lee todo lo que le cae en las manos, hasta la lista de componentes del gel de baño mientras se ducha ¡sin gafas!), y en sus ratos libres se dedica a hacer cosas como ésta, algún que otro programa Open Source para Windows como zxFortune, responder en los foros de las news y a poner entradas en su blog.