Academic Tutorials



English | French | Portugese | German | Italian
Home Advertise Payments Recommended Websites Interview Questions FAQs
News Source Codes E-Books Downloads Jobs Web Hosting
Chats

VC++
VC++ Introduction
VC++ What's New
VC++ Supported Platforms
Visual C++ Settings
VC++ Breaking Changes
Visual C++ Walkthroughs
Visual C++ Editions
VC++ Project Templates
Visual C++ Guided Tour
VC++ Creating Command-Line Applications
VC++ Windows Applications
VC++ Reusable Code
VC++ Porting
VC++ Unix Users
VC++ Upgrade Wizard
VC++ Migration Primer
VC++ Managed Types
VC++ Member Declarations
VC++ Conversion Operators
VC++ Interface Member
VC++ Value Types
VC++ Boxed Value
VC++ General Language
VC++ Common Programming
VC++ Database Support
VC++ MFC Database Classes
VC++ Record
VC++ Record View
VC++ OLE DB Programming

HTML Tutorials
HTML Tutorial
XHTML Tutorial
CSS Tutorial
TCP/IP Tutorial
CSS 1.0
CSS 2.0
HLML
XML Tutorials
XML Tutorial
XSL Tutorial
XSLT Tutorial
DTD Tutorial
Schema Tutorial
XForms Tutorial
XSL-FO Tutorial
XML DOM Tutorial
XLink Tutorial
XQuery Tutorial
XPath Tutorial
XPointer Tutorial
RDF Tutorial
SOAP Tutorial
WSDL Tutorial
RSS Tutorial
WAP Tutorial
Web Services Tutorial
Browser Scripting
JavaScript Tutorial
VBScript Tutorial
DHTML Tutorial
HTML DOM Tutorial
WMLScript Tutorial
E4X Tutorial
Server Scripting
ASP Tutorial
PERL Tutorial
SQL Tutorial
ADO Tutorial
CVS
Python
Apple Script
PL/SQL Tutorial
SQL Server
PHP
.NET (dotnet)
Microsoft.Net
ASP.Net
.Net Mobile
C# : C Sharp
ADO.NET
VB.NET
VC++
Multimedia
SVG Tutorial
Flash Tutorial
Media Tutorial
SMIL Tutorial
Photoshop Tutorial
Gimp Tutorial
Matlab
Gnuplot Programming
GIF Animation Tutorial
Scientific Visualization Tutorial
Graphics
Web Building
Web Browsers
Web Hosting
W3C Tutorial
Web Building
Web Quality
Web Semantic
Web Careers
Weblogic Tutorial
SEO
Web Site Hosting
Domain Name
Java Tutorials
Java Tutorial
JSP Tutorial
Servlets Tutorial
Struts Tutorial
EJB Tutorial
JMS Tutorial
JMX Tutorial
Eclipse
J2ME
JBOSS
Programming Langauges
C Tutorial
C++ Tutorial
Visual Basic Tutorial
Data Structures Using C
Cobol
Assembly Language
Mainframe
Forth Programming
Lisp Programming
Pascal
Delphi
Fortran
OOPs
Data Warehousing
CGI Programming
Emacs Tutorial
Gnome
ILU
Soft Skills
Communication Skills
Time Management
Project Management
Team Work
Leadership Skills
Corporate Communication
Negotiation Skills
Database Tutorials
Oracle
MySQL
Operating System
BSD
Symbian
Unix
Internet
IP-Masquerading
IPC
MIDI
Software Testing
Testing
Firewalls
SAP Module
ERP
ABAP
Business Warehousing
SAP Basis
Material Management
Sales & Distribution
Human Resource
Netweaver
Customer Relationship Management
Production and Planning
Networking Programming
Corba Tutorial
Networking Tutorial
Microsoft Office
Microsoft Word
Microsoft Outlook
Microsoft PowerPoint
Microsoft Publisher
Microsoft Excel
Microsoft Front Page
Microsoft InfoPath
Microsoft Access
Accounting
Financial Accounting
Managerial Accounting
Network Sites


The Managed Types


Previoushome Next






The Managed Types
The syntax for the declaration of managed types and the creation and use of objects of these types has been significantly altered from Managed Extensions for C++ to Visual C++ 2008.
A D V E R T I S E M E N T
This was done to promote their integration within the ISO-C++ type system. These changes are presented in detail in the following subsections.



In This Section
Declaration of a Managed Class Type
Discusses how to declare a managed class, struct, or interface.
Declaration of a CLR Reference Class Object
Discusses how to declare a reference class type object using a tracking handle.
Declaration of a CLR Array
Explains how to declare and initialize an array.
Changes in Constructor Initialization Order
Discusses key changes in class constructor initialization order.
Changes in Destructor Semantics
Discusses non-deterministic finalization, Finalize versus Dispose, ramifications for reference objects, and use of an explicit Finalize.

Note: The discussion of delegates is deferred until Delegates and Events in order to present them with event members within a class, the general topic of Member Declarations within a Class or Interface.

Declaration of a Managed Class Type
The way to declare a reference class type changed from Managed Extensions for C++ to Visual C++ 2008.

In Managed Extensions, a reference class type is prefaced with the __gc keyword. In the new syntax, the __gc keyword is replaced by one of two spaced keywords: ref class or ref struct. The choice of struct or class indicates the public (for struct) or private (for class) default access level of its members declared in an initial unlabeled section of the body of the type.

Similarly, in Managed Extensions, a value class type is prefaced with the __value keyword. In the new syntax, the __value keyword is replaced by one of two spaced keywords: value class or value struct.

An interface type, in Managed Extensions, was indicated with the keyword __interface. In the new syntax, this is replaced with interface class.

For example, the following class declarations in Managed Extensions:

Copy Code
public __gc class Block {};     // reference class
public __value class Vector {}; // value class
public __interface IFooBar {};  // interface class

Under the new syntax these are equivalently declared as follows:

Copy Code
public ref class Block {};         // reference class
public value class Vector {};      // value class
public interface class IFooBar {}; // interface class



Specifying the Class as Abstract

Under Managed Extensions, you put the keyword __abstract before the class keyword (either before or after the __gc) to indicate that the class is incomplete and that objects of the class cannot be created within the program:

Copy Code
public __gc __abstract class Shape {};
public __gc __abstract class Shape2D: public Shape {};

Under the new syntax, you specify the abstract contextual keyword following the class name and before either the class body, base class derivation list, or semicolon.

Copy Code
public ref class Shape abstract {};
public ref class Shape2D abstract : public Shape{};

Of course, the semantic meaning is unchanged.




Specifying the Class as Sealed

Under Managed Extensions, you put the keyword __sealed before the class keyword (either before or after __gc) to indicate that objects of the class cannot be inherited from:

Copy Code
public __gc __sealed class String {};

Under the new syntax, you specify the sealed contextual keyword following the class name and before either the class body, base class derivation list, or semicolon.

You can both derive a class and seal it. For example, the String class is implicitly derived from Object. The benefit of sealing a class is that it supports the static resolution (that is, at compile-time) of all virtual function calls through the sealed reference class object. This is because the sealed specifier guarantees that the String tracking handle cannot refer to a subsequently derived class that might provide an overriding instance of the virtual method being invoked. Here is an example of a sealed class in new syntax:

Copy Code
public ref class String sealed {};

One can also specify a class as both abstract and sealed – this is a special condition that indicates a static class. This is described in the CLR documentation as follows:

"A type that is both abstract and sealed should have only static members, and serves as what some languages call a namespace."

For example, here is a declaration of an abstract sealed class using the Managed Extensions syntax:

Copy Code
public __gc __sealed __abstract class State {
public:
   static State() {}
   static bool inParamList();

private:
   static bool ms_inParam;
};

and here is this declaration translated into the new syntax:

Copy Code
public ref class State abstract sealed {
public:
   static State();
   static bool inParamList();

private:
   static bool ms_inParam;
};



CLR Inheritance: Specifying the Base Class

Under the CLR object model, only public single inheritance is supported. However, Managed Extensions retained the ISO-C++ default interpretation of a base class without an access keyword as specifying a private derivation. This meant that each CLR inheritance declaration had to provide the public keyword to override the default interpretation.

Copy Code
// Managed Extensions: error: defaults to private derivation
__gc class Derived : Base {};

In the new syntax definition, the absence of an access keyword indicates a public derivation in a CLR inheritance definition. Thus, the public access keyword is now optional. While this does not require any modification of Managed Extensions for C++ code, I list this change here for completeness.

Copy Code
// New syntax: ok: defaults to public derivation
ref class Derived : Base{};
Declaration of a CLR Reference Class Object
The syntax to declare and instantiate an object of a reference class type has changed from Managed Extensions for C++ to Visual C++ 2008.

In Managed Extensions, a reference class type object is declared by using the ISO-C++ pointer syntax, with an optional use of the __gc keyword to the left of the star (*). For example, here are a variety of reference class type object declarations under the Managed Extensions syntax:

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

   void PrintValues( Array* myArr ) {
      System::Collections::IEnumerator* myEnumerator = 
         myArr->GetEnumerator();

      Array *localArray;
      myArr->Copy(myArr, localArray, myArr->Length);
   }
};

Under the new syntax, you declare a reference class type object by using a new declarative token (^) referred to formally as a tracking handle and more informally as a hat. (The tracking adjective means that a reference type sits in the CLR heap, and can therefore transparently move locations during garbage collection heap compaction. A tracking handle is transparently updated during runtime. Two similar concepts are the tracking reference (%), and the interior pointer (interior_ptr<>), discussed in class="normaltext".

The primary reasons to move the declarative syntax away from a reuse of the ISO-C++ pointer syntax are as follows:

  • The use of the pointer syntax did not permit overloaded operators to be directly applied to a reference object. Rather, one had to call the operator by using its internal name, such as rV1->op_Addition(rV2) instead of the more intuitive rV1+rV2.
  • A number of pointer operations, such as casting and pointer arithmetic, not permitted for objects stored on a garbage collected heap. The notion of a tracking handle better captures the nature of a CLR reference type.

The __gc modifier on a tracking handle is unnecessary and is not supported. The use of the object itself is not changed; it still accesses members through the pointer member selection operator (->). For example, here is the previous Managed Extensions code sample translated into the new syntax:

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

   void PrintValues( Array^ myArr ) {
      System::Collections::IEnumerator^ myEnumerator =
         myArr->GetEnumerator();

      Array ^localArray;
      myArr->Copy(myArr, localArray, myArr->Length);   }
};



Dynamic Allocation of an Object on the CLR Heap

In Managed Extensions, the existence of two new expressions to allocate between the native and managed heap was largely transparent. In almost all instances, the compiler is able to use the context to determine whether to allocate memory from the native or managed heap. For example,

Copy Code
Button *button1 = new Button; // OK: managed heap
int *pi1 = new int;           // OK: native heap
Int32 *pi2 = new Int32;       // OK: managed heap

When you do not want the contextual heap allocation, you could direct the compiler with either the __gc or __nogc keyword. In the new syntax, the separate nature of the two new expressions is made explicit with the introduction of the gcnew keyword. For example, the previous three declarations look as follows in the new syntax:

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

Here is the Managed Extensions initialization of the Form1 members declared in the previous section:

Copy Code
void InitializeComponent() {
   components = new System::ComponentModel::Container();
   button1 = new System::Windows::Forms::Button();
   myDataGrid = new DataGrid();

   button1->Click += 
      new System::EventHandler(this, &Form1::button1_Click);
}

Here is the same initialization recast to the new syntax. Note that the hat is not required for the reference type when it is the target of a gcnew expression.

Copy Code
void InitializeComponent() {
   components = gcnew System::ComponentModel::Container;
   button1 = gcnew System::Windows::Forms::Button;
   myDataGrid = gcnew DataGrid;

   button1->Click += 
      gcnew System::EventHandler( this, &Form1::button1_Click );
}



A Tracking Reference to No Object

In the new syntax, 0 no longer represents a null address but is treated as an integer, the same as 1, 10, or 100. A new special token represents a null value for a tracking reference. For example, in Managed Extensions, we initialize a reference type to address no object as follows:

Copy Code
// OK: we set obj to refer to no object
Object * obj = 0;

// Error: no implicit boxing
Object * obj2 = 1;

In the new syntax, any initialization or assignment of a value type to an Object causes an implicit boxing of that value type. In the new syntax, both obj and obj2 are initialized to addressed boxed Int32 objects holding the values 0 and 1, respectively. For example:

Copy Code
// causes the implicit boxing of both 0 and 1
Object ^ obj = 0;
Object ^ obj2 = 1;

Therefore, in order to perform the explicit initialization, assignment, and comparison of a tracking handle to null, use a new keyword, nullptr. The correct revision of the original example looks as follows:

Copy Code
// OK: we set obj to refer to no object
Object ^ obj = nullptr;

// OK: we initialize obj2 to a Int32^
Object ^ obj2 = 1;

This complicates somewhat the porting of existing code into the new syntax. For example, consider the following value class declaration:

Copy Code
__value struct Holder {
   Holder( Continuation* c, Sexpr* v ) {
      cont = c;
      value = v;
      args = 0;
      env = 0;
   }

private:
   Continuation* cont;
   Sexpr * value;
   Environment* env;
   Sexpr * args __gc [];
};

Here, both args and env are CLR reference types. The initialization of these two members to 0 in the constructor cannot remain unchanged in the transition to the new syntax. Rather, they must be changed to nullptr:

Copy Code
value struct Holder {
   Holder( Continuation^ c, Sexpr^ v )
   {
      cont = c;
      value = v;
      args = nullptr;
      env = nullptr;
   }

private:
   Continuation^ cont;
   Sexpr^ value;
   Environment^ env;
   array^ args;
};

Similarly, tests against those members comparing them to 0 must also be changed to compare the members to nullptr. Here is the Managed Extensions syntax:

Copy Code
Sexpr * Loop (Sexpr* input) {
   value = 0;
   Holder holder = Interpret(this, input, env);

   while (holder.cont != 0) {
      if (holder.env != 0) {
         holder=Interpret(holder.cont,holder.value,holder.env);
      }
      else if (holder.args != 0) {
         holder = 
         holder.value->closure()->
         apply(holder.cont,holder.args);
      }
   }

   return value;
}

Here is the revision, replacing each 0 instance with a nullptr. The translation tool helps in this transformation by automating many if not all occurrences, including use of the NULL macro.

Copy Code
Sexpr ^ Loop (Sexpr^ input) {
   value = nullptr;
   Holder holder = Interpret(this, input, env);

   while ( holder.cont != nullptr ) {
      if ( holder.env != nullptr ) {
         holder=Interpret(holder.cont,holder.value,holder.env);
      }
      else if (holder.args != nullptr ) {
         holder = 
         holder.value->closure()->
         apply(holder.cont,holder.args);
      }
   }

   return value;
}

The nullptr is converted into any pointer or tracking handle type but is not promoted to an integral type. For example, in the following set of initializations, the nullptr is valid only as an initial value to the first two.

Copy Code
// OK: we set obj and pstr to refer to no object
Object^ obj = nullptr;
char*   pstr = nullptr; // 0 would also work here

// Error: no conversion of nullptr to 0 …
int ival = nullptr;

Similarly, given an overloaded set of methods such as the following:

Copy Code
void f( Object^ ); // (1)
void f( char* );   // (2)
void f( int );     // (3)

An invocation with nullptr literal, such as the following,

Copy Code
// Error: ambiguous: matches (1) and (2)
f(  nullptr );

is ambiguous because the nullptr matches both a tracking handle and a pointer, and there is no preference given to one type over the other. (This situation requires an explicit cast in order to disambiguate.)

An invocation with 0 exactly matches instance (3):

Copy Code
// OK: matches (3)
f( 0 );

because 0 is of type integer. Were f(int) not present, the call would unambiguously match f(char*) through a standard conversion. The matching rules give precedence of an exact match over a standard conversion. In the absence of an exact match, a standard conversion is given precedence over an implicit boxing of a value type. That is why there is no ambiguity.

Declaration of a CLR Array
The syntax for declaring, instantiating, and initializing a managed array has changed from Managed Extensions for C++ to Visual C++ 2008.

The declaration of a CLR array object in Managed Extensions was an extension of the standard array declaration in which a __gc keyword was placed between the name of the array object and its possibly comma-filled dimension, as in the following pair of examples:

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

This has been simplified in the new syntax, in which we use a template-like declaration similar to the STL vector declaration. The first parameter indicates the element type. The second parameter specifies the array dimension (with a default value of 1, so only multiple dimensions require a second argument). The array object itself is a tracking handle, and so must be given a hat. If the element type is also a reference type, it also requires a hat. For example, the above example, when expressed in the new syntax, looks as follows:

Copy Code
void PrintValues( array^ myArr );
void PrintValues( array^ myArr );

Because a reference type is a tracking handle rather than an object, it is possible to specify a CLR array as the return type of a function. (In contrast, it is not possible to specify the native array as the return type of a function.) The syntax for doing this in Managed Extensions was somewhat non-intuitive. For example:

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

In Visual C++ 2008, the declaration is much simpler. For example,

Copy Code
array^ f();
array^ GetArray();

The shorthand initialization of a local managed array is supported in both versions of the language. For example:

Copy Code
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;
}

is considerably simplified in the new syntax (note that because boxing is implicit in the new syntax, the __box operator has been eliminated – see Value Types and Their Behaviors for a discussion):

Copy Code
array^ GetArray() {
   array^ a1 = {1,2,3,4,5};
   array^ myObjArray = {26,27,28,29,30};
   return a1;
}

Because an array is a CLR reference type, the declaration of each array object is a tracking handle. Therefore, array objects must be allocated on the CLR heap. (The shorthand notation hides the managed heap allocation.) Here is the explicit form of an array object initialization under Managed Extensions:

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

Under the new syntax, the new expression is replaced with gcnew. The dimension sizes are passed as parameters to the gcnew expression, as follows:

Copy Code
array^ myArray = gcnew array(2);
array^ myMat = gcnew array(4,4);

In the new syntax, an explicit initialization list can follow the gcnew expression; this was not supported in Managed Extensions. For example:

Copy Code
// explicit initialization list following gcnew 
// was not supported in Managed Extensions
array^ myArray = 
   gcnew array(4){ 1, 1, 2, 3 };
Changes in Constructor Initialization Order
The order of initialization for class constructors has changed from Managed Extensions for C++ to Visual C++ 2008.



Comparison of Constructor Initialization Order

Under Managed Extensions for C++, constructor initialization occurred in the following order:

  1. The constructor of the base class, if any, is invoked.
  2. The initialization list of the class is evaluated.
  3. The code body of the class constructor is executed.

This order of execution follows the same conventions as in native C++ programming. The new Visual C++ language prescribes the following execution order for CLR classes:

  1. The initialization list of the class is evaluated.
  2. The constructor of the base class, if any, is invoked.
  3. The code body of the class constructor is executed.

Note this change applies only to CLR classes; native classes in Visual C++ 2008 still follow the previous conventions. In both cases, these rules cascade upward throughout the whole hierarchy chain of a given class.

Consider the following code example using Managed Extensions for C++:

Copy Code
__gc class A
{
public:
   A() : _n(1)
   {
   }

protected:
   int _n;
};

__gc class B : public A
{
public:
   B() : _m(_n)
   {
   }
private:
   int _m;
};

Following the constructor initialization order prescribed above, we should see the following order of execution when new instances of class B are constructed:

  1. The constructor of the base class A is invoked. The _n member is initialized to 1.
  2. The initialization list for class B is evaluated. The _m member is initialized to 1.
  3. The code body of class B is executed.

Now consider the same code in the new Visual C++ syntax:

Copy Code
ref class A
{
public:
   A() : _n(1)
   {
   }

protected:
   int _n;
};

ref class B : A
{
public:
   B() : _m(_n)
   {
   }
private:
   int _m;
};

The order of execution when new instances of class B are constructed under the new syntax is:

  1. The initialization list for class B is evaluated. The _m member is initialized to 0 (0 is the uninitialized value of the _m class member).
  2. The constructor of the base class A is invoked. The _n member is initialized to 1.
  3. The code body of class B is executed.

Note that a similar syntax produces different results for these code examples. The constructor of class B depends on a value from base class A to initialize its member. However, the constructor for class A has not yet been invoked. Such a dependency can be especially dangerous when the inherited class depends on a memory or resource allocation to occur in the base class constructor.




What This Means Going from Managed Extensions for C++ to Visual C++ 2005

In many cases the changes to the execution order of class constructors should be transparent to the programmer because base classes have no notion of the behavior of inherited classes. However, as these code examples illustrate, the constructors of inherited classes can be greatly affected when their initialization lists depend on the values of base class members. When you move your code from Managed Extensions for C++ to the new syntax, consider moving such constructs to the body of the class constructor, where execution is guaranteed to occur last.

Changes in Destructor Semantics
Semantics for class destructors have changed significantly from Managed Extensions for C++ to Visual C++ 2008.

In Managed Extensions, a class destructor was permitted within a reference class but not within a value class. This has not changed in the new syntax. However, the semantics of the class destructor have changed. This topic focuses on the reasons of that change and discusses how it affects the translation of existing CLR code. It is probably the most important programmer-level change between the two versions of the language.




Non-deterministic Finalization

Before the memory associated with an object is reclaimed by the garbage collector, an associated Finalize method, if present, is invoked. You can think of this method as a kind of super-destructor because it is not tied to the program lifetime of the object. We refer to this as finalization. The timing of just when or even whether a Finalize method is invoked is undefined. This is what we mean when we say that garbage collection exhibits non-deterministic finalization.

Non-deterministic finalization works well with dynamic memory management. When available memory becomes scarce, the garbage collector kicks in. Under a garbage collected environment, destructors to free memory are unnecessary. Non-deterministic finalization does not work well, however, when an object maintains a critical resource such as a database connection or a lock of some sort. In this case, we should release that resource as soon as possible. In the native world, that is achieved by using a constructor/destructor pair. As soon as the lifetime of the object ends, either when the local block within which it is declared ends, or when the stack unravels because of a thrown exception, the destructor executes and the resource is automatically released. This approach works very well, and its absence under Managed Extensions was sorely missed.

The solution provided by the CLR is for a class to implement the Dispose method of the IDisposable interface. The problem here is that Dispose requires an explicit invocation by the user. This is error-prone. The C# language provides a modest form of automation in the form of a special using statement. The Managed Extensions design provided no special support.




Destructors in Managed Extensions for C++

In Managed Extensions, the destructor of a reference class is implemented by using the following two steps:

  1. The user-supplied destructor is renamed internally to Finalize. If the class has a base class (remember, under the CLR Object Model, only single inheritance is supported), the compiler injects a call to its finalizer following execution of the user-supplied code. For example, consider the following simple hierarchy taken from the Managed Extensions language specification:
Copy Code
__gc class A {
public:
   ~A() { Console::WriteLine(S"in ~A"); }
};
   
__gc class B : public A {
public:
   ~B() { Console::WriteLine(S"in ~B");  }
};

In this example, both destructors are renamed Finalize. B's Finalize has an invocation of A's Finalize method added following the invocation of WriteLine. This is what the garbage collector will by default invoke during finalization. Here is what this internal transformation might look like:

Copy Code
// internal transformation of destructor under Managed Extensions
__gc class A {
public:
   void Finalize() { Console::WriteLine(S"in ~A"); }
};

__gc class B : public A {
public:
   void Finalize() { 
      Console::WriteLine(S"in ~B");
      A::Finalize(); 
   }
};
  1. In the second step, the compiler synthesizes a virtual destructor. This destructor is what our Managed Extensions user programs invoke either directly or through an application of the delete expression. It is never invoked by the garbage collector.

    Two statements are placed within this synthesized destructor. One is a call to GC::SuppressFinalize to make sure that there are no more invocations of Finalize. The second is the actual invocation of Finalize, which represents the user-supplied destructor for that class. Here is what this might look like:

Copy Code
__gc class A {
public:
   virtual ~A() {
      System::GC::SuppressFinalize(this);
      A::Finalize();
   }
};

__gc class B : public A {
public:
   virtual ~B() {
      System::GC::SuppressFinalize(this);
      B::Finalize();
   }
};

While this implementation allows the user to explicitly invoke the class Finalize method now rather than at a time you have no control over, it does not really tie in with the Dispose method solution. This is changed in Visual C++ 2008.




Destructors in New Syntax

In the new syntax, the destructor is renamed internally to the Dispose method and the reference class is automatically extended to implement the IDispose interface. That is, under Visual C++ 2008, our pair of classes is transformed as follows:

Copy Code
// internal transformation of destructor under the new syntax
__gc class A : IDisposable {
public:
   void Dispose() { 
      System::GC::SuppressFinalize(this);
      Console::WriteLine( "in ~A");
   }
};

__gc class B : public A {
public:
   void Dispose() { 
      System::GC::SuppressFinalize(this);
      Console::WriteLine( "in ~B");  
      A::Dispose(); 
   }
};

When either a destructor is invoked explicitly under the new syntax, or when delete is applied to a tracking handle, the underlying Dispose method is invoked automatically. If it is a derived class, a call of the Dispose method of the base class is inserted at the close of the synthesized method.

But this does not get us all the way to deterministic finalization. In order to reach that, we need the additional support of local reference objects. (This has no analogous support within Managed Extensions, and so it is not a translation issue.)




Declaring a Reference Object

Visual C++ 2008 supports the declaration of an object of a reference class on the local stack or as a member of a class as if it were directly accessible. When combined with the association of the destructor with the Dispose method, the result is the automated invocation of finalization semantics on reference types.

First, we define our reference class such that object creation functions as the acquisition of a resource through its class constructor. Secondly, within the class destructor, we release the resource acquired when the object was created.

Copy Code
public ref class R {
public:
   R() { /* acquire expensive resource */ }
   ~R() { /* release expensive resource */ }

   // … everything else …
};

The object is declared locally by using the type name but without the accompanying hat. All uses of the object, such as invoking a method, are done through the member selection dot (.) instead of arrow (->). At the end of the block, the associated destructor, transformed into Dispose, is invoked automatically, as shown here:

Copy Code
void f() {
   R r; 
   r.methodCall();

   // r is automatically destructed here –
   // that is, r.Dispose() is invoked
}

As with the using statement within C#, this does not defy the underlying CLR constraint that all reference types must be allocated on the CLR heap. The underlying semantics remain unchanged. The user could equivalently have written the following (and this is likely the internal transformation performed by the compiler):

Copy Code
// equivalent implementation
// except that it should be in a try/finally clause
void f() {
   R^ r = gcnew R; 
   r->methodCall();

   delete r;
}

In effect, under the new syntax, destructors are again paired with constructors as an automated acquisition/release mechanism tied to a local object's lifetime.




Declaring an Explicit Finalize

In the new syntax, as we've seen, the destructor is synthesized into the Dispose method. This means that when the destructor is not explicitly invoked, the garbage collector, during finalization, will not as before find an associated Finalize method for the object. To support both destruction and finalization, we have introduced a special syntax for providing a finalizer. For example:

Copy Code
public ref class R {
public:
   !R() { Console::WriteLine( "I am the R::finalizer()!" ); }
};

The ! prefix is analogous to tilde (~) that introduces a class destructor – that is, both post-lifetime methods have a token prefixing the name of the class. If the synthesized Finalize method occurs within a derived class, an invocation of the base class Finalize method is inserted at its end. If the destructor is explicitly invoked, the finalizer is suppressed. Here is what the transformation might look like:

Copy Code
// internal transformation under new syntax
public ref class R {
public:
   void Finalize() {
      Console::WriteLine( "I am the R::finalizer()!" );
   }
}; 



Moving from Managed Extensions for C++ to Visual C++ 2005

The runtime behavior of a Managed Extensions for C++ program is changed when it is compiled under Visual C++ 2008 whenever a reference class contains a non-trivial destructor. The required translation algorithm is similar to the following:

  1. If a destructor is present, rewrite that to be the class finalizer.
  2. If a Dispose method is present, rewrite that into the class destructor.
  3. If a destructor is present but there is no Dispose method, retain the destructor while performing the first item.

In moving your code from Managed Extensions to the new syntax, you might miss performing this transformation. If the application depended in some way on the execution of associated finalization methods, the behavior of the application will silently differ from the one you intended.



Be the first one to comment on this page.




  VC++ eBooks

No eBooks on VC++ could be found as of now.

 
 VC++ FAQs
More Links » »
 
 VC++ Interview Questions
More Links » »
 
 VC++ Articles
More Links » »
 
 VC++ News
More Links » »
 
 VC++ Jobs
More Links » »

Share And Enjoy:These icons link to social bookmarking sites where readers can share and discover new web pages.
  • blinkbits
  • BlinkList
  • blogmarks
  • co.mments
  • connotea
  • del.icio.us
  • De.lirio.us
  • digg
  • Fark
  • feedmelinks
  • Furl
  • LinkaGoGo
  • Ma.gnolia
  • NewsVine
  • Netvouz
  • RawSugar
  • Reddit
  • scuttle
  • Shadows
  • Simpy
  • Smarking
  • Spurl
  • TailRank
  • Wists
  • YahooMyWeb

Previoushome Next

Keywords: bsd programming language, bsd language programming tutorial pdf, history of bsd programming, basic bsd programming, bsd band satellite programming, syntax use in bsd programming, bsd programming software download, turbo bsd programming, bsd programming code, learn bsd programming

HTML Quizzes
HTML Quiz
XHTML Quiz
CSS Quiz
TCP/IP Quiz
CSS 1.0 Quiz
CSS 2.0 Quiz
HLML Quiz
XML Quizzes
XML Quiz
XSL Quiz
XSLT Quiz
DTD Quiz
Schema Quiz
XForms Quiz
XSL-FO Quiz
XML DOM Quiz
XLink Quiz
XQuery Quiz
XPath Quiz
XPointer Quiz
RDF Quiz
SOAP Quiz
WSDL Quiz
RSS Quiz
WAP Quiz
Web Services Quiz
Browser Scripting Quizzes
JavaScript Quiz
VBScript Quiz
DHTML Quiz
HTML DOM Quiz
WMLScript Quiz
E4X Quiz
Server Scripting Quizzes
ASP Quiz
PERL Quiz
SQL Quiz
ADO Quiz
CVS Quiz
Python Quiz
Apple Script Quiz
PL/SQL Quiz
SQL Server Quiz
PHP Quiz
.NET (dotnet) Quizzes
Microsoft.Net Quiz
ASP.Net Quiz
.Net Mobile Quiz
C# : C Sharp Quiz
ADO.NET Quiz
VB.NET Quiz
VC++ Quiz
Multimedia Quizzes
SVG Quiz
Flash Quiz
Media Quiz
SMIL Quiz
Photoshop Quiz
Gimp Quiz
Matlab Quiz
Gnuplot Programming Quiz
GIF Animation Quiz
Scientific Visualization Quiz
Graphics Quiz
Web Building Quizzes
Web Browsers Quiz
Web Hosting Quiz
W3C Quiz
Web Building Quiz
Web Quality Quiz
Web Semantic Quiz
Web Careers Quiz
Weblogic Quiz
SEO Quiz
Web Site Hosting Quiz
Domain Name Quiz
Java Quizzes
Java Quiz
JSP Quiz
Servlets Quiz
Struts Quiz
EJB Quiz
JMS Quiz
JMX Quiz
Eclipse Quiz
J2ME Quiz
JBOSS Quiz
Programming Langauges Quizzes
C Quiz
C++ Quiz
Visual Basic Quiz
Data Structures Using C Quiz
Cobol Quiz
Assembly Language Quiz
Mainframe Quiz
Forth Programming Quiz
Lisp Programming Quiz
Pascal Quiz
Delphi Quiz
Fortran Quiz
OOPs Quiz
Data Warehousing Quiz
CGI Programming Quiz
Emacs Quiz
Gnome Quiz
ILU Quiz
Soft Skills Quizzes
Communication Skills Quiz
Time Management Quiz
Project Management Quiz
Team Work Quiz
Leadership Skills Quiz
Corporate Communication Quiz
Negotiation Skills Quiz
Database Quizzes
Oracle Quiz
MySQL Quiz
Operating System Quizzes
BSD Quiz
Symbian Quiz
Unix Quiz
Internet Quiz
IP-Masquerading Quiz
IPC Quiz
MIDI Quiz
Software Testing Quizzes
Testing Quiz
Firewalls Quiz
SAP Module Quizzes
ERP Quiz
ABAP Quiz
Business Warehousing Quiz
SAP Basis Quiz
Material Management Quiz
Sales & Distribution Quiz
Human Resource Quiz
Netweaver Quiz
Customer Relationship Management Quiz
Production and Planning Quiz
Networking Programming Quizzes
Corba Quiz
Networking Quiz
Microsoft Office Quizzes
Microsoft Word Quiz
Microsoft Outlook Quiz
Microsoft PowerPoint Quiz
Microsoft Publisher Quiz
Microsoft Excel Quiz
Microsoft Front Page Quiz
Microsoft InfoPath Quiz
Microsoft Access Quiz
Accounting Quizzes
Financial Accounting Quiz
Managerial Accounting Quiz
Testimonials | Contact Us | Link to Us | Site Map
Copyright ? 2008. Academic Tutorials.com. All rights reserved Privacy Policies | About Us
Our Portals : Academic Tutorials | Best eBooksworld | Beyond Stats | City Details | Interview Questions | Discussions World | Excellent Mobiles | Free Bangalore | Give Me The Code | Gog Logo | Indian Free Ads | Jobs Assist | New Interview Questions | One Stop FAQs | One Stop GATE | One Stop GRE | One Stop IAS | One Stop MBA | One Stop SAP | One Stop Testing | Webhosting in India | Dedicated Server in India | Sirf Dosti | Source Codes World | Tasty Food | Tech Archive | Testing Interview Questions | Tests World | The Galz | Top Masala | Vyom | Vyom eBooks | Vyom International | Vyom Links | Vyoms | Vyom World | Important Websites
Copyright ? 2003-2024 Vyom Technosoft Pvt. Ltd., All Rights Reserved.