Share via

From the February 2002 issue of MSDN Magazine

MSDN Magazine

Still in Love with C++

Modern Language Features Enhance the Visual C++ .NET Compiler

Stanley B. Lippman
This article assumes you're familiar with C++
Level of Difficulty     1   2   3 
SUMMARY Programmers who have been using C++ for years are wondering where their language is headed with the advent of C# and Microsoft .NET. This article sketches a roadmap of C++ as it is used in the world of .NET. In .NET there are two approaches to C++ code: managed and unmanaged. Unmanaged code doesn't use the CLR, while managed code involves the use of Managed Extensions for C++. This discussion explains both approaches.

Those of us in the C++ community feel somewhat like the older child in a family when the new baby is brought home for the first time. Everybody goes gaga over the new little tyke, and we're lucky if we even get a pat on the head. It's hard not to feel ignored and a little bit hurt. Actually, it's even worse in technology because the ground is constantly shifting, and keeping abreast is a matter of survival.
      Of course, today the Microsoft® .NET Framework is the new technology on the block—quite a feast at that, and everyone is oohing and aahing about the language called C#. If you're a C++ programmer, it is hard not to wonder if you ought to learn C#. After all, in the .NET discussion there is hardly a mention of C++, except to contrast it with C#.
      Are C++ programmers obsolete? Absolutely not! In this article I'll touch on what's new in the current release of Visual Studio® .NET, and then give you some idea of the plans Microsoft has for the future of C++. Primarily, there are two aspects of C++ in Visual Studio .NET that I want to touch on: standard C++ and the Managed Extensions for C++.
      The motivation behind the recent progress in standard C++ was largely to maintain compliance; that is, to provide support for the International Organization for Standardization (ISO) language features. I'll also talk about the Managed Extensions for C++ in terms of making C++ a .NET language.

Standard C++ in Visual Studio .NET

      Progress has been made in standards compliance within the following areas:

  • There is now covariant return type support in the definition of virtual functions. This is great news for those who write class hierarchies.
  • Static const integer members can now be initialized explicitly.
  • There is support for the implicit return of 0 within main.

Now I'll discuss each area briefly.
      Adding the covariant return type was the first modification of the C++ language approved by the standards committee. This is a fancy way of saying that the virtual function of a derived class can now return an instance of the derived class when the base class virtual function it is overriding returns an instance of the base class. It's an important design idiom in the support for class hierarchies, and it is a welcome addition to Visual Studio .NET.
      Here is an example of how it is typically used. Consider this abstract Query base class:

  class Query {
virtual Query *clone() = 0;
// ...


In the NotQuery derived class instance, clone returns a copy of a NotQuery object. For example:

  class NotQuery {
virtual ???? clone()
{ return new NotQuery( this ); }
// ...
Query *operand;


Without support for covariant return types, the return type of the NotQuery instance of clone must be Query*:

  // without covariant return type support
virtual Query* clone()
{ return new NotQuery(
this ); }


This works fine if you are assigning the return value of clone to a Query* pointer, like so:

  NotQuery::NotQuery( const NotQuery &rhs )
{ operand = rhs.operand->clone(); }


But this fails when you want to explicitly assign its value to a NotQuery*, as in:

  NotQuery nq( new NameQuery( "Shakespeare" );

// oops: illegal assignment ...
NotQuery *pnq0 = nq->clone();

// ok: required explicit cast ...
NotQuery *pnq1 =


      With covariant return type support, you can explicitly declare the NotQuery clone instance to return a NotQuery*:

  // with covariant return type support
virtual NotQuery* clone()
{ return new NotQuery( this ); }


This allows you to use clone in an intuitive fashion without requiring an explicit cast:

  // ok: implicit conversion �
Query *pq = nq->clone();

// ok: no conversion necessary �
NotQuery *pnq = nq->clone();


      While explicit initialization of a static const integer member is not as critical a language feature as that of covariant return type, it provides an important design convenience in class situations requiring a constant expression, such as the definition of a fixed-size array. For example:

  class Buffer {
static const int ms_buf_size = 1024;
char m_buffer[ ms_buf_size ];


      A static const integer member is the one instance in C++ in which a class member can be initialized explicitly within the class definition, thereby making the value available to other constructs within the class, such as the dimension size of m_buffer. Without this construct, the use of an enumerator as a symbolic constant was a common workaround.
      The return value of main represents a program's exit status. By convention, an exit status of zero indicates program success. With standard C++, a main function without an explicit return value means the compiler inserts a

  return 0;


prior to the end of main. With Visual Studio .NET, Visual C++® is finally compliant with this standard.

Managed C++ in Visual Studio .NET

      The Managed Extensions for C++ in Visual Studio .NET allow for three primary application strategies:

  • They provide a .NET-managed wrapper class to an unmanaged API, thereby exposing existing C++ classes to the Microsoft .NET platform.
  • They allow you to make use of the Microsoft .NET class framework, intermixing it with unmanaged C++. There are three aspects to the framework: core language support, such as collection classes and system I/O; foundation programming classes, such as support for threading, network sockets, and regular expressions; and application domain support, such as XML, ASP.NET and Web Services, Windows Forms, ADO.NET, and so on.
  • They let you write directly in the .NET environment just as you might with C# or Visual Basic®. With this release, however, there is no C++ support for RAD designers, such as those for Windows® Forms and Web Forms.

      First, I'll discuss wrapping an unmanaged implementation. For the third edition of my book C++ Primer (Addison-Wesley, 1998), I created a relatively large text query application which heavily exercises the STL container classes for parsing a text file and setting up an internal representation. Figure 1 shows the include file and Figure 2 shows the data representation.
      Query is the abstract base class of an object-oriented hierarchy for interpreting a query language. Figure 3 shows how a query session might run. The native invocation of the text query system looks like this:

  int main()
TextQuery tq;


I want to expose the TextQuery interface to the .NET platform without having to touch the darn thing, let alone consider reimplementing it. After all, it works. I wasn't sure if I wanted to move to the .NET platform if it meant I had to give up on my investment in native code. Fortunately, wrapping native code to expose it to the .NET platform is an important benefit of managed C++. Figure 4 shows what the code for doing this looks like.
      The __gc modifier (shown in Figure 4) identifies the class as a managed class—a garbage collected class allocated on the common language runtime's managed heap. I declare the native class as a pointer member. I allocate it on the unmanaged heap through the new expression, the same as I do in native code. Because it is not garbage collected, I delete it within the destructor. Both build_up_text and query_text serve as stub functions, dispatching the call to the actual TextQuery object.
      Figure 5 shows the revised main function, generated by the managed C++ project wizard.
      Now let's discuss how to make use of the .NET Framework. If someone were to ask me what is the most significant weakness of ISO Standard C++, I would say it's the fact that there is no standard library for programming domains such as threading, network programming, regular expressions, XML, and so on. The Standards committee is planning to address this deficiency in its next cycle, but that's years from now. What do you do in the meantime? Fortunately, the .NET Framework provides an attractive solution. For example, Figure 6 shows a simple Socket server class utilizing the .NET Framework. It accepts phone number queries for employees of Northwind, the sample SQL database distributed with Visual Studio .NET.
      Figure 7 is a sample output created by running the server and recording its handling of three clients. Figure 8 shows the implementation of the Start function shown in Figure 6. The Start function makes use of the Thread class to spawn independent threads to retrieve the data from the database and handle client connections. Because WriteLine requires a reference parameter, you need to explicitly box the port value.
      The Exception class is the root of the .NET exception hierarchy. The ToString method displays a full stack trace, which is very cool. ThreadStart is a delegate type—a kind of generic pointer to both static and nonstatic member functions.
      I could go further into the implementation, but I think you can get a sense of the framework's power and ease of use. More importantly, you can see how easy it is to make use of it through C++.

The Future of C++

      Hopefully after reading this brief look at C++ in Visual Studio .NET, you feel reassured that Visual C++ is not only still a member of the family, but an important family member at that! To underscore that importance, the Visual C++ team at Microsoft is working hard on an interim release to deliver these features as soon as possible. In terms of ISO Standard C++, the team has made exceptional strides in compliance work. For the power programmer, this means templates, templates, templates. Third-party libraries that heavily utilize templates, such as Loki and Boost, now compile internally without workarounds. As they say in Hollywood, stick around. You ain't seen nothing yet!

For related articles see:
Visual C++ .NET: What's New for MFC Developers?
Visual Studio .NET: Managed Extensions Bring .NET CLR Support to C++
Bugslayer: Optimize and Trim Your Code with New Switches in Visual C++ .NET
Hello World in Managed Extensions for C++


For background information see:
Essential C++ (Addison-Wesley)


Stanley B. Lippman is a new architect with the Visual C++ development team at Microsoft. He spent more than 12 years at Bell Laboratories where he worked on the original cfront C++ implementation. Stan is the author of C++ Primer, Inside the C++ Object Model, Essential C++, and the recent C# Primer, all published by Addison-Wesley.