C


C++

C# was a brand new language created just for the .NET Framework. The .NET-based version of VB was essentially the same thing, although its name and syntactic style were borrowed from VB 6. But C++ existed well before .NET, and it's been in wide use for many years. Given this, Microsoft decided that while providing some way to create CLR-based software in C++ was essential, so was maintaining compatibility with the existing language. Unlike VB, Microsoft believed that making everyone move to a purely CLR-based version of C++ wasn't a good idea. Accordingly, Visual Studio 2005, like its predecessors, still supports standard C++.

C++ was too popular for the .NET Framework's creators to ignore


Yet mapping C++ to the CLR presented some challenges. Most important, the original semantics of C++ don't exactly match those of the CLR. They have much in commonboth are object-oriented, for examplebut there are also many differences. C++, for instance, supports multiple inheritance, the ability of a class to inherit simultaneously from two or more parent classes, while the CLR does not.

The semantics of C++ differ from those of the CLR


VB 6 also differed substantially from the CLR, but Microsoft owned VB. The company was free to change it as they wished, so VB's .NET-based incarnation was designed to match the CLR. Microsoft does not own C++, however. Unilaterally changing the language itself to match the CLR would have met with howls of protest. Yet providing no way to create .NET Frameworkbased applications in C++ would also have left many developers unhappy. What's the solution?

Unlike VB, Microsoft isn't free to change C++ unilaterally to fit the CLR


The original answer Microsoft chose was to create a set of extensions to the base C++ language. Officially known as Managed Extensions for C++, the resulting dialect is commonly referred to as just Managed C++. C++ is not simple to begin with, and Managed C++ added new complexities. Despite this, Managed C++ was used by a number of organizations for creating .NET applications.

Microsoft originally defined a set of Managed Extensions for C++


With the 2005 release of the Visual Studio, Microsoft has provided another way to create managed code in C++. While the original managed extensions are still supported, they're now deprecated. Instead, the C++ language itself has been modified, adding new keywords and more for creating applications that run on the CLR. Expressly designed for creating managed code, this language dialect is known as C++/CLI. These extensions are following the standardization path originally defined for the CLI, with the goal of potentially making the C++/CLI dialect available in non-Microsoft environments. This section provides a brief introduction to both C++/CLI and the Managed C++ dialect it replaces.

Perspective: C++ or C#?

C++ has legions of die-hard fans. And why shouldn't it? It's a powerful, flexible tool for building all kinds of applications. It's complicated, too, which means that learning to exploit all that power and flexibility takes a substantial amount of effort. Anyone who's put in the time to master C++ is bound to be less than thrilled about leaving it behind.

Yet for brand-new applications built from scratch on the .NET Framework, C++ probably should be left behind. For a C++ developer, learning C# isn't difficult. In fact, learning C# will probably be easier than using either C++/CLI or Managed C++ to write .NET Frameworkbased applications. As the short summary in this chapter suggests, these language extensions add even more complexity to an already complex language. For new applications, C# is probably a better choice.

For extending existing C++ applications with managed code, however, C++/CLI is a good choice. And if you plan to port an existing C++ application to run on the Framework, C++/CLI is also a good choice, since it saves you from rewriting large parts of your code. Although it's not as widely used in the .NET Framework world as either VB or C#, C++ is nevertheless an important part of .NET's language arsenal.


The 2005 release of C++ adds direct language extensions for creating managed code


C++/CLI

Before looking at a C++/CLI example, it's useful to briefly describe some of the extensions made to the language. To make writing CLR-based code as natural as possible, Microsoft chose to add several keywords to the language. To avoid breaking existing C++ code, these keywords use two interesting approaches:

  • Contextual keywords have meaning only in a specific context. For example, the keyword sealed on a declaration specifies that no other type can inherit from this one, just as in C#. This keyword only has meaning when it appears in the context of a declaration, however. This allows existing programs that use the identifier sealed in another way, such as for a variable name, to work unchanged.

  • Spaced keywords are pairs of terms that are treated as a single unit. For instance, a C++/CLI interface is defined using the spaced keywords interface class. As with a contextual keyword, the identifier interface has a special meaning only in this context, so existing code that uses it in other ways won't break.

With these ideas in mind, we can now make some sense out of an example.

A C++/CLI Example

Here's the same simple program shown earlier in C# and VB, this time expressed in C++/CLI. As before, the semantics are essentially the same. What's changed is the syntax in which those semantics are expressed.

// A C++/CLI example #include "stdafx.h" interface class IMath {     int Factorial(int f);     double SquareRoot(double s); }; ref class Compute : public IMath {     public: virtual int Factorial(int f)     {         int i;         int result = 1;         for (i=2; i<=f; i++)             result = result * i;         return result;     };     public: virtual double SquareRoot(double s)     {         return System::Math::Sqrt(s);     } }; void main(void) {     Compute ^c = gcnew Compute;     int v;     v = 5;     System::Console::WriteLine(       "{0} factorial: {1}",       v, c->Factorial(v));     System::Console::WriteLine(       "Square root of {0}: {1:f4}",       v, c->SquareRoot(v)); }


The first thing to notice is how much this example resembles the C# version. Most of the basic syntax and many of the operators are the same. Yet it's different, too, beginning with the #include statement necessary for creating managed code in C++. Following these, the interface IMath is defined, just as before. This time, however, it uses the spaced keyword interface class, described above. The result is a C++ incarnation of a CTS-defined interface.

C++/CLI resembles C#


Next comes the class Compute, which implements the IMath interface. This class is prefaced with C++/CLI's ref class keyword, which indicates that this is a CTS reference class, one whose lifetime is managed by the CLR using garbage collection. The class itself varies a bit in syntax from the C# example, since C++ doesn't express things in exactly the same way, but it's nonetheless very similar.

A CTS class is defined with ref class


The example ends with a standard C++ main function. Just as in the earlier examples, it creates an instance of the Compute class and then calls its two methods, all using standard C++ syntax. The most visible difference from those earlier examples (and from standard C++) is the use of the gcnew keyword. This keyword indicates that an instance of a CTS class (i.e., a garbage-collected class, hence the "gc" in "gcnew") is being created. In other words, the Compute class is being created on the heap managed by the CLR rather than on the native heap maintained by C++. (Objects instantiated using the standard C++ new operator are created on this native heap, just as always.)

Instances of CTS reference types are created using gcnew


Another difference is the appearance of the ^ symbol, commonly called a caret or, more informally, a hat, in the declaration of the Compute class. Standard C++ uses the traditional asterisk to indicate a reference. To make immediately clear that a CTS reference type is involved, however, C++/CLI introduces the idea of a handle. Identified by this new symbol, a handle like the one declared here can sometimes be used in ways similar to an ordinary C++ pointer, as shown by the calls to Factorial and SquareRoot later in the program. Because it's actually a reference to a garbage-collected object on the CLR-managed heap, however, it is in fact quite different from an ordinary C++ pointer. This new syntax makes that difference very visible to developers. And just as you'd expect, the output of this example is the same as before: the factorial and square root of five.

A CTS class is referenced via a handle


C++/CLI Types

C++/CLI allows full access to the .NET Framework, including the types defined by the CLR and more. It's important to note that managed and unmanaged code, classes defined with and without ref, can be defined in the same file, and they can exist in the same running process. Only the managed classes are subject to garbage collection, however; unmanaged classes must be explicitly freed as usual in C++. Table 3-3 shows some of the major CTS types and their equivalents in C++/CLI.

Table 3-3. Some CTS Types and Their C++/CLI Equivalents

CTS

C++/CLI

Byte

unsigned char

Char

wchar_t

Int16

short, signed short

Int32

int, signed int, long, signed long

Int64

__int64, signed __int64

UInt16

unsigned short

UInt32

unsigned int, unsigned long

UInt64

unsigned __int64

Single

float

Double

double, long double

Decimal

Decimal

Boolean

bool

Class

ref class, ref struct

Interface

interface class

Delegate

delegate


Managed and unmanaged C++ code can coexist in a process


Other C++/CLI Features

Because it fully supports the CLR, there's much more in C++/CLI. Properties can be created using the property keyword, for example, while delegates can be created using the delegate keyword. C++/CLI supports both CLR-defined generics and their cousins, standard C++ templates. Namespaces can be referenced with a using namespace statement, such as

using namespace System;


Exceptions can be handled using try/catch blocks, and custom CLR exceptions that inherit from System::Exception can be created. Attributes can also be embedded in code using a syntax much like that used in C#.

C++/CLI allows full access to what the CLR provides


Except for C++, all languages in Visual Studio compile only to MSIL, and they require the .NET Framework to run. Since all C++/CLI classes are compiled to MSIL, the language can obviously be used to generate Framework-based code. Yet C++ is unique among Microsoft's .NET-based languages in that it also allows compiling directly to a machine-specific binary. For building Windows applications that don't require the CLR, this makes C++ the only way to go.

C++ is the only language in Visual Studio 2005 that can compile directly to native code


Managed C++

Visual Studio .NET, Microsoft's original tool for creating .NET applications, introduced Managed C++ for creating CLR-based software in C++. With the release of Visual Studio 2005, the use of Managed C++ is now discouraged. Still, plenty of people wrote (or more often extended) C++ applications using this original attempt at combining C++ and the CLR. Given this, it's worth taking a quick look at this now-deprecated dialect. It's also interesting to compare it with its successor, C++/CLI.

Using Managed C++ is deprecated today


Before looking at a Managed C++ example, though, it's useful to describe some of the extensions made to the language. Like C++/CLI, several keywords were added to allow access to CLR services. These keywords all begin with two underscores, following the convention defined in the ANSI standard for C++ extensions. Among the most important of these are the following:

  • __gc: Indicates a CTS type that is subject to garbage collection, i.e., a CTS reference type.

  • __value: Indicates a CTS type that is not subject to garbage collection, i.e., a CTS value type.

  • __interface: Used to define a CTS interface type.

  • __box: An operation that converts a CTS value type to a reference type. Unlike C#, VB, and C++/CLI, Managed C++ does not implicitly perform boxing and unboxing operations. Instead, developers are required to indicate explicitly where these conversions should occur.

  • __unbox: An operation that converts a boxed CTS value type back to its original form.

Like C++/CLI, Managed C++ defined several new keywords


As before, an example is now in order.

A Managed C++ Example

Here's this chapter's standard example, this time in Managed C++:

// A Managed C++ example #include "stdafx.h" #using <mscorlib.dll> __gc __interface IMath {     int Factorial(int f);     double SquareRoot(double s); }; __gc class Compute : public IMath {     public: int Factorial(int f)     {         int i;         int result = 1;         for (i=2; i&lt;=f; i++)             result = result * i;         return result;     };     public: double SquareRoot(double s)     {         return System::Math::Sqrt(s);     } }; void main(void) {     Compute *c = new Compute;     int v;     v = 5;     System::Console::WriteLine(       "{0} factorial: {1}",       box(v), __box(c->Factorial(v)));     System::Console::WriteLine(       "Square root of {0}: {1:f4}",       box(v), __box(c->SquareRoot(v))); }


Not too surprisingly, this example looks similar to the versions shown earlier in C# and C++/CLI. The differences are interesting, however, and they start with the #include and #using statements necessary for creating Managed C++ code. The interface IMath is once again defined, but this time, it uses the __interface keyword and precedes it with the __gc keyword. The combination has the same meaning as interface class in C++/CLI. The Compute class is also declared with the __gc keyword, expressing in a different way what C++/CLI says with ref.

Managed C++ resembles C++/CLI and C#


The example ends with a standard C++ main function. Just as before, it creates an instance of the Compute class and then calls its two methods, all using standard C++ syntax. The only substantive difference is in the calls to WriteLine. Because this method expects reference parameters, the __box operator must be used to pass the numeric parameters correctly. Boxing also occurred for this parameter in C# and VB, but it was done automatically. Because C++ was not originally built for the CLR, however, a Managed C++ developer must explicitly request this operation.

Managed C++ requires explicit boxing


Managed C++ Types

Like C++/CLI, Managed C++ allows full access to the .NET Framework, lets managed and unmanaged code be defined in the same file, and more. To a very large degree, the two C++ dialects just provide different ways of expressing identical semantics. Table 3-4 shows some of the major CLR types and their equivalents in Managed C++.

Table 3-4. Some CLR Types and Their Managed C++ Equivalents

CLR

Managed C++

Byte

unsigned char

Char

wchar_t

Int16

short

Int32

int, long

Int64

__int64

UInt16

unsigned short

UInt32

unsigned int, unsigned long

UInt64

unsigned __int64

Single

float

Double

double

Decimal

Decimal

Boolean

bool

Class

__gc class

Interface

__gc __interface

Delegate

__delegate


Managed C++ is functionally similar to C++/CLI


Other Managed C++ Features

Like C++/CLI, Managed C++ provides full access to the CLR. Delegates can be created using the __delegate keyword, namespaces can be referenced with using namespace, just as in C++/CLI, exceptions and attributes can be used, and more. Managed C++ isn't a weak tool, and its use wasn't deprecated because it lacked power. Rather, the people at Microsoft who control this technology felt that their first attempt at mapping C++ to the CLR wasn't good enough, and so going forward, new C++ managed code should be created using C++/CLI instead.

Perspective: Is C++ a Dying Language?

C++ was the workhorse of professional software developers for most of the 1990s. It's been used to write Lotus Notes, a surfeit of business applications, and even parts of Windows. Yet in a world that offers C#, a modern version of VB, and Java, where does C++ fit? Has its usefulness come to an end?

Certainly not. C#, VB, and Java are much better than C++ for many types of applications, even many for which C++ has commonly been used. But all three of these languages operate in a virtual machine environment. This has many benefits, but there's also a price: performance and size. Some categories of software, such as certain real-time applications or system-level code, can't afford this.

Still, the day when C++ was the default choice for building a broad range of new applications has ended. In the Microsoft world, C# and VB are the new defaults, while Java dominates elsewhere. Yet in cases where none of these is appropriateand they do existC++ will still dominate. Its role has surely shrunk, but C++ is not about to disappear.


Managed C++ also allows full access to the CLR's features





Understanding. NET
Understanding .NET (2nd Edition)
ISBN: 0321194047
EAN: 2147483647
Year: 2004
Pages: 67

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net