Outline of Changes (C++/CLI)

 

The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.

The latest version of this topic can be found at Outline of Changes (C++/CLI).

This outline shows you examples of some of the changes in the language from Managed Extensions for C++ to Visual C++. Follow the link that accompanies each item for more information.

No Double Underscore Keywords

The double underscore in front of all keywords has been removed, with one exception. Thus, __value becomes value, and __interface becomes interface, and so on. To prevent name clashes between keywords and identifiers in user code, keywords are primarily treated as contextual.

See Language Keywords (C++/CLI) for more information.

Class Declarations

Managed Extensions syntax:

__gc class Block {};                           // reference class  
__value class Vector {};                       // value class  
__interface I {};                        // interface class  
__gc __abstract class Shape {};                // abstract class  
__gc __sealed class Shape2D : public Shape {}; // derived class  

New syntax:

ref class Block {};                // reference class  
value class Vector {};             // value class  
interface class I {};        // interface class  
ref class Shape abstract {};       // abstract class  
ref class Shape2D sealed: Shape{}; // derived class  

See Managed Types (C++/CL) for more information.

Object Declaration

Managed Extensions syntax:

public __gc class Form1 : public System::Windows::Forms::Form {  
private:  
   System::ComponentModel::Container __gc *components;  
   System::Windows::Forms::Button   __gc *button1;  
   System::Windows::Forms::DataGrid __gc *myDataGrid;     
   System::Data::DataSet  __gc *myDataSet;  
};  

New syntax:

public ref class Form1 : System::Windows::Forms::Form {  
   System::ComponentModel::Container^ components;  
   System::Windows::Forms::Button^ button1;  
   System::Windows::Forms::DataGrid^ myDataGrid;  
   System::Data::DataSet^ myDataSet;  
};  

See Declaration of a CLR Reference Class Object for more information.

Managed Heap Allocation

Managed Extensions syntax:

Button* button1 = new Button; // managed heap  
int *pi1 = new int;           // native heap  
Int32 *pi2 = new Int32;       // managed heap  

New syntax:

Button^ button1 = gcnew Button;        // managed heap  
int * pi1 = new int;                   // native heap  
Int32^ pi2 = gcnew Int32;              // managed heap  

See Declaration of a CLR Reference Class Object for more information.

A Tracking Reference to No Object

Managed Extensions syntax:

// OK: we set obj to refer to no object  
Object * obj = 0;  
  
// Error: no implicit boxing  
Object * obj2 = 1;  

New syntax:

// Incorrect Translation  
// causes the implicit boxing of both 0 and 1  
Object ^ obj = 0;  
Object ^ obj2 = 1;  
  
// Correct Translation  
// OK: we set obj to refer to no object  
Object ^ obj = nullptr;  
  
// OK: we initialize obj2 to an Int32^  
Object ^ obj2 = 1;  

See Declaration of a CLR Reference Class Object for more information.

Array Declaration

The CLR array has been redesigned. It is similar to the stl vector template collection, but maps to the underlying System::Array class – that is, it is not a template implementation.

See Declaration of a CLR Array for more information.

Array as Parameter

Managed Extensions array syntax:

void PrintValues( Object* myArr __gc[]);   
void PrintValues( int myArr __gc[,,]);   

New array syntax:

void PrintValues( array<Object^>^ myArr );  
void PrintValues( array<int,3>^ myArr );  

Array as Return Type

Managed Extensions array syntax:

Int32 f() [];   
int GetArray() __gc[];  

New array syntax:

array<Int32>^ f();  
array<int>^ GetArray();  

Shorthand Initialization of Local CLR Array

Managed Extensions array syntax:

int GetArray() __gc[] {  
   int a1 __gc[] = { 1, 2, 3, 4, 5 };  
   Object* myObjArray __gc[] = { __box(26), __box(27), __box(28),  
                                 __box(29), __box(30) };  
  
   return a1;  
}  

New array syntax:

array<int>^ GetArray() {  
   array<int>^ a1 = {1,2,3,4,5};  
   array<Object^>^ myObjArray = {26,27,28,29,30};  
  
   return a1;  
}  

Explicit CLR Array Declaration

Managed Extensions array syntax:

Object* myArray[] = new Object*[2];  
String* myMat[,] = new String*[4,4];  

New array syntax:

array<Object^>^ myArray = gcnew array<Object^>(2);  
array<String^,2>^ myMat = gcnew array<String^,2>(4,4);  

New to language: explicit array initialization that follows gcnew

// explicit initialization list follow gcnew   
// is not supported in Managed Extensions  
array<Object^>^ myArray =   
   gcnew array<Object^>(4){ 1, 1, 2, 3 };  

Scalar Properties

Managed Extensions property syntax:

public __gc __sealed class Vector {  
   double _x;  
  
public:  
   __property double get_x(){ return _x; }  
   __property void set_x( double newx ){ _x = newx; }  
};  

New property syntax:

public ref class Vector sealed {   
   double _x;  
  
public:  
   property double x   
   {  
      double get()             { return _x; }  
      void   set( double newx ){ _x = newx; }  
   } // Note: no semi-colon …  
};  

New to language: trivial properties

public ref class Vector sealed {   
public:  
   // equivalent shorthand property syntax  
   // backing store is not accessible  
   property double x;   
};  

See Property Declaration for more information.

Indexed Properties

Managed Extensions indexed property syntax:

public __gc class Matrix {  
   float mat[,];  
  
public:   
   __property void set_Item( int r, int c, float value) { mat[r,c] = value; }  
   __property int get_Item( int r, int c ) { return mat[r,c]; }  
};  

New indexed property syntax:

public ref class Matrix {  
   array<float, 2>^ mat;  
  
public:  
   property float Item [int,int] {  
      float get( int r, int c ) { return mat[r,c]; }  
      void set( int r, int c, float value ) { mat[r,c] = value; }  
   }  
};  

New to language: class-level indexed property

public ref class Matrix {  
   array<float, 2>^ mat;  
  
public:  
   // ok: class level indexer now  
   //     Matrix mat;  
   //     mat[ 0, 0 ] = 1;   
   //  
   // invokes the set accessor of the default indexer  
  
   property float default [int,int] {  
      float get( int r, int c ) { return mat[r,c]; }  
      void set( int r, int c, float value ) { mat[r,c] = value; }  
   }  
};  

See Property Index Declaration for more information.

Overloaded Operators

Managed Extensions operator overload syntax:

public __gc __sealed class Vector {  
public:  
   Vector( double x, double y, double z );  
  
   static bool    op_Equality( const Vector*, const Vector* );  
   static Vector* op_Division( const Vector*, double );  
};  
  
int main() {  
   Vector *pa = new Vector( 0.231, 2.4745, 0.023 );  
   Vector *pb = new Vector( 1.475, 4.8916, -1.23 );   
  
   Vector *pc = Vector::op_Division( pa, 4.8916 );  
  
   if ( Vector::op_Equality( pa, pc ))  
      ;  
}  

New operator overload syntax:

public ref class Vector sealed {  
public:  
   Vector( double x, double y, double z );  
  
   static bool    operator ==( const Vector^, const Vector^ );  
   static Vector^ operator /( const Vector^, double );  
};  
  
int main() {  
   Vector^ pa = gcnew Vector( 0.231, 2.4745, 0.023 );  
   Vector^ pb = gcnew Vector( 1.475, 4.8916, -1.23 );  
  
   Vector^ pc = pa / 4.8916;  
   if ( pc == pa )  
      ;  
}  

See Overloaded Operators for more information.

Conversion Operators

Managed Extensions conversion operator syntax:

__gc struct MyDouble {  
   static MyDouble* op_Implicit( int i );   
   static int op_Explicit( MyDouble* val );  
   static String* op_Explicit( MyDouble* val );   
};  

New conversion operator syntax:

ref struct MyDouble {  
public:  
   static operator MyDouble^ ( int i );  
   static explicit operator int ( MyDouble^ val );  
   static explicit operator String^ ( MyDouble^ val );  
};  

See Changes to Conversion Operators for more information.

Explicit Override of an Interface Member

Managed Extensions explicit override syntax:

public __gc class R : public ICloneable {  
   // to be used through ICloneable  
   Object* ICloneable::Clone();  
  
   // to be used through an R  
   R* Clone();  
};  

New explicit override syntax:

public ref class R : public ICloneable {  
   // to be used through ICloneable  
   virtual Object^ InterfaceClone() = ICloneable::Clone;  
  
   // to be used through an R   
   virtual R^ Clone();  
};  

See Explicit Override of an Interface Member for more information.

Private Virtual Functions

Managed Extensions private virtual function syntax:

__gc class Base {  
private:  
   // inaccessible to a derived class  
   virtual void g();   
};  
  
__gc class Derived : public Base {  
public:  
   // ok: g() overrides Base::g()  
   virtual void g();  
};  

New private virtual function syntax

ref class Base {  
private:  
   // inaccessible to a derived class  
   virtual void g();   
};  
  
ref class Derived : public Base {  
public:  
   // error: cannot override: Base::g() is inaccessible  
   virtual void g() override;  
};  

See Private Virtual Functions for more information.

CLR Enum Type

Managed Extensions enum syntax:

__value enum e1 { fail, pass };  
public __value enum e2 : unsigned short  {   
   not_ok = 1024,   
   maybe, ok = 2048   
};    

New enum syntax:

enum class e1 { fail, pass };  
public enum class e2 : unsigned short {   
   not_ok = 1024,  
   maybe, ok = 2048   
};  

Apart from this small syntactic change, the behavior of the CLR enum type has been changed in a number of ways:

  • A forward declaration of a CLR enum is no longer supported.

  • The overload resolution between the built-in arithmetic types and the Object class hierarchy has reversed between Managed Extensions and Visual C++. As a side-effect, CLR enums are no longer implicitly converted to arithmetic types.

  • In the new syntax, a CLR enum maintains its own scope, which is not the case in Managed Extensions. Previously, enumerators were visible within the containing scope of the enum; now, enumerators are encapsulated within the scope of the enum.

See CLR Enum Type for more information.

Removal of __box Keyword

Managed Extensions boxing syntax:

Object *o = __box( 1024 ); // explicit boxing  

New boxing syntax:

Object ^o = 1024; // implicit boxing  

See A Tracking Handle to a Boxed Value for more information.

Pinning Pointer

Managed Extensions pinning pointer syntax:

__gc struct H { int j; };  
  
int main() {  
   H * h = new H;  
   int __pin * k = & h -> j;  
};  

New pinning pointer syntax:

ref struct H { int j; };  
  
int main() {  
   H^ h = gcnew H;  
   pin_ptr<int> k = &h->j;  
}  

See Value Type Semantics for more information.

__typeof Keyword becomes typeid

Managed Extensions typeof syntax:

Array* myIntArray =   
   Array::CreateInstance( __typeof(Int32), 5 );  

New typeid syntax:

Array^ myIntArray =   
   Array::CreateInstance( Int32::typeid, 5 );  

See typeof Goes to T::typeid for more information.

See Also

C++/CLI Migration Primer
(NOTINBUILD)Managed Extensions for C++ Syntax Upgrade Checklist
Component Extensions for Runtime Platforms