< Old To New C++ .Net version 7 | Main | Old To New C++ .Net version 9 >


 

 

Early Stages of the C++ .Net 30

(From Managed Extensions for C++ to new C++ .NET Syntax)

 

 

The code snippets used in this module if any are Visual C++ .Net 2003 dominated and if compiled using Visual C++ .Net 2005 you need to use the /clr:oldSyntax option). The following are the topics available in this module.

  1. Managed Extensions for C++: __box Keyword

  2. Implicit Boxing

 

Managed Extensions for C++: __box Keyword

 

This topic applies only to version 1 of Managed Extensions for C++. This syntax should only be used to maintain version 1 code. Use Implicit Boxing for the equivalent functionality in the new syntax. This keyword creates a managed copy of a __value class object. The syntax is:

__box(value-class identifier)

The __box keyword is used to create a managed object (derived from System::ValueType) from an existing __value class object. When the __box keyword is applied to a __value class:

  1. A managed object is allocated on the common language runtime heap.

  2. The current value of the __value class object is bit-wise copied into the managed object.

  3. The address of the new managed object is returned.

This process is known as boxing. This enables any __value class object to be used in generic routines that work for any managed object because the managed object indirectly inherits from System::Object since System::ValueType inherits from System::Object. The newly created boxed object is a copy of the __value class object. Therefore, modifications to the value of the boxed object do not affect the contents of the __value class object. The following is an example that does boxing and unboxing:

 

// Test.cpp : main project file.

// keyword __box

// compile with: /clr:oldSyntax

#include "stdafx.h"

#using <mscorlib.dll>

 

using namespace System;

 

int main()

{

      Int32 i = 100;

      System::Object* obj = __box(i);

      Console::WriteLine("i = {0}", obj);

      Int32 j = *dynamic_cast<__box Int32*>(obj);

      Console::Write("j = ");

      Console::WriteLine(j);

 

      return 0;

}

 

Output:

__box, .Net C++ boxing - convertin the value type as an object

 

In the following example, an unmanaged value type (V) is boxed and passed as a managed parameter to the Positive function.

// Test.cpp : main project file.

// keyword, __box

// compile with: /clr:oldSyntax

#include "stdafx.h"

#using <mscorlib.dll>

 

using namespace System;

 

__value struct myV

{

      int i;

};

 

// expects a managed class

void Positive(Object*) {}

 

int main()

{

      // allocate and initialize

      myV myv = {100};

      Console::Write("myv.i = ");

      Console::WriteLine(myv.i);

      // copy to the common language runtime heap

      __box myV* pBoxedV = __box(myv);

      // treat as a managed class

      Positive(pBoxedV);

      // update the boxed version

      pBoxedV->i = 200;

      Console::Write("pBoxedV->i = ");

      Console::WriteLine(pBoxedV->i);

 

   return 0;

}

 

Output:

__box keyword for boxing the value type as an object program output

 

 

 

 

Implicit Boxing

 

The Visual C++ compiler now boxes value types to Object. This is possible because of a compiler-defined conversion to convert value types to Object. Boxing and unboxing enable value types to be treated as objects. Value types, including both struct types and built-in types such as int, can be converted to and from the type Object. The following sample shows how explicit boxing was done with Managed Extensions for C++.

// Test.cpp : main project file.

// explicit boxing

// compile with: /clr:oldSyntax

#include "stdafx.h"

#using <mscorlib.dll>

 

using namespace System;

 

__gc class A

{

      public:

            void func(System::Object * o){Console::WriteLine("In class A...");}

};

 

__value class V {};

 

__gc __interface IFace

{

      void func();

};

 

__value class V1 : public IFace

{

      public:

            void func()

            { Console::WriteLine("In interface function..."); }

};

 

int main()

{

      // example 1 explicit boxing

      Int32 __box* bi = __box(100);

      Console::Write("bi = ");

      Console::WriteLine(bi);

      // example 2 calling a member with explicit boxing

      Int32 n = 200;

      Console::WriteLine(S"n = {0}", __box(n)->ToString());

      // example 3 explicit boxing for function calls

      A * a = new A;

      a->func(__box(n));

      // example 4  explicit boxing for WriteLine function call

      V v;

      Console::WriteLine(S"Class {0} passed using implicit boxing", __box(v)->ToString());

      // example 5 casting to a base with explicit boxing

      V1 v1;

      IFace * iface = __box(v1);

      iface->func();

   return 0;

}

 

Output:

C++ .NET - implicit boxing, new C++ .NET

 

The following sample shows how implicit boxing works.

// Test.cpp : main project file.

// explicit boxing2 example

// compile with: /clr

#include "stdafx.h"

 

using namespace System;

 

ref class A

{

      public:

            void func(System::Object^ o){Console::WriteLine("In class A...");}

};

 

value class V {};

 

interface struct IFace

{

      void func();

};

 

value class V1 : public IFace

{

      public:

            virtual void func()

            { Console::WriteLine("In funct, interface function..."); }

};

 

value struct V2

{

      // conversion operator to System::Object

      static operator System::Object^(V2 v2)

      {

            Console::WriteLine("Operator System::Object^...");

            return (V2^)v2;

      }

};

 

void func1(System::Object^){Console::WriteLine("In void func1(System::Object^)");}

void func1(V2^){Console::WriteLine("In func1(V2^)");}

 

void func2(System::ValueType^){Console::WriteLine("In func2(System::ValueType^)");}

void func2(System::Object^){Console::WriteLine("In func2(System::Object^)");}

 

int main()

{

      // example 1 simple implicit boxing

      Int32^ bi = 100;

      Console::Write("bi = ");

      Console::WriteLine(bi);

      // example 2 calling a member with implicit boxing

      Int32 n = 200;

      Console::WriteLine("n = {0}", n.ToString());

      // example 3 implicit boxing for function calls

      A^ a = gcnew A;

      a->func(n);

      // example 4 implicit boxing for WriteLine function call

      V v;

      Console::WriteLine("Class {0} passed using implicit boxing", v);

      // force boxing

      Console::WriteLine("Class {0} passed with forced boxing", (V^)(v));

      // example 5 casting to a base with implicit boxing

      V1 v1;

      IFace ^ iface = v1;

      iface->func();

      // example 6 user-defined conversion preferred over implicit boxing

      // for function-call parameter matching

      V2 v2;

      // user defined conversion from V2 to System::Object preferred

      // over implicit boxing will call void func1(System::Object^);

      func1(v2);

      // OK: Calls "static V2::operator System::Object^(V2 v2)"

      func2(v2);

      // Using explicit boxing: calls func2(System::ValueType^)

      func2((V2^)v2);

 

      return 0;

}

 

Output:

How implicit boxing work - program output C++ .NET

 

Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7 | Part 8 | Part 9

 

 


< Old To New C++ .Net version 7 | Main | Old To New C++ .Net version 9 >