< Old To New C++ .Net version 1 | Main | Old To New C++ .Net version 3 >


 

 

Early Stages of the C++ .Net 24

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

 

 

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

  1. Managed Extensions for C++: __nogc keyword

  2. Using the equivalent functionality in the new C++ syntax: Classes and Structs (Managed)

  3. Managed Extensions for C++: __interface keyword

 

 

 

 

Managed Extensions for C++: __nogc keyword

 

This should applies only to version 1 of Managed Extensions for C++. This syntax should only be used to maintain version 1 code. The __nogc explicitly declares an unmanaged type. The syntaxes are shown below.  In the new syntax, you do not need to explicitly mark a type as unmanaged.

  1. __nogc class-specifier

  2. __nogc struct-specifier

  3. __nogc interface-specifier

  4. __nogc array-specifier

  5. __nogc pointer-specifier

  6. __nogc new

The __nogc keyword is used to explicitly specify that an object is allocated on the standard C++ heap. This keyword is optional. If you don't specify __gc or __nogc in front of a class declaration, it defaults to __nogc. Objects of this type are similar to standard C++ objects in that they are allocated from the standard C++ heap and are not subject to the restrictions of a managed object. The __nogc keyword is also used when an object of a __value type is explicitly allocated on the standard C++ heap:

// compile with: /clr:oldSyntax

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

 

__value struct V

{

   int i;

};

int main()

{

   V * v = __nogc new V;

   v->i = 10;

   Console::Write(S"v->i = ");

   Console::WriteLine(v->i);

   delete v;

}

 

Output:

program output for __value and __nogc new keywords

 

The __nogc keyword can also be applied to array and pointer types. A gc pointer cannot be a member of a __nogc class. In the following example, an unmanaged class is declared (X) and an object is instantiated and modified:

// compile with: /clr:oldSyntax

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;

 

__nogc class X {

public:

   int i;

};

 

int main()

{

   X* x;          // declares an unmanaged pointer of type X

   x = new X();   // creates unmanaged object of type X on the C++ heap

   Console::Write(S"x = new X() then x->i = ");

   Console::WriteLine(x->i);

 

   x->i = 100;   // modifies unmanaged object

   Console::Write(S"x->i = 100 then x->i = ");

   Console::WriteLine(x->i);

 

   delete x;   // call C++ delete operator to clean up resource

}

 

Output:

 

__nogc class and new keywords program output

 

Using the equivalent functionality in the new C++ syntax: Classes and Structs (Managed)

 

The following syntaxes are new C++ keywords that declare a managed class or struct replacing the keywords used in Managed Extension for C++.

  1. class_access ref class name modifier : inherit_access base_type {};

  2. class_access ref struct name modifier : inherit_access base_type {};

  3. class_access value class name modifier : inherit_access base_type {};

  4. class_access value struct name modifier : inherit_access base_type {};

The description is listed in the following table.

 

Parameter

Description

base_type (optional)

A base type. A ref class or ref struct can inherit from zero or more managed interfaces and zero or one ref types. A value class or value struct can only inherit from zero or more managed interfaces.

class_access (optional)

The accessibility of the class or struct outside the assembly. Possible values are public and private. private is the default. Nested classes or structs cannot have a class_access specifier.

inherit_access (optional)

The accessibility of base_type. The only permitted accessibility for a base type is public (public is the default).

modifier (optional)

abstract and sealed are valid modifiers.

name

The name of the class or struct.

 

Table 2

 

Like their native C++ equivalents, default member accessibility of a ref class or value class is private and default member accessibility of a ref struct or value struct is public. A value type cannot act as a base type. When a reference type inherits from another reference type, virtual functions in the base class must explicitly be overridden (with override) or hidden (with new (new slot in vtable)). The derived class functions must also be explicitly marked as virtual. You can detect at compile time if a type is a CLR type with __is_ref_class(type), __is_value_class(type), or __is_simple_value_class(type). In the development environment, you can get F1 help on these keywords by highlighting the keyword, (ref class, for example) and pressing F1.

// ref class, VC++ EE 2005

// compile with: /clr

#using <mscorlib.dll>

// System.Console.WriteLine

using namespace System;

 

ref class MyClass {

public:

   int i;

 

   ref class MyClass2 {

   public:

      int i;

   };

 

   interface struct MyInterface { void f(); };

};

 

ref class MyClass2 : MyClass::MyInterface {

public:

   virtual void f() { System::Console::WriteLine("just some text #1"); }

};

 

value struct MyStruct {

   void f()

   { System::Console::WriteLine("just some text #2"); }

};

 

int main()

{

      MyClass testval;

      MyClass2 testval1;

      MyStruct testval2;

 

      testval.i = 100;

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

      Console::WriteLine(testval.i);

 

      Console::Write("testval1.f() ==> ");

      testval1.f();

      Console::Write("testval2.f() ==> ");

      testval2.f();

 

      return 0;

}

 

Output:

ref class and value struct program output

 

Managed Extensions for C++: __interface keyword

 

This is Microsoft Specific. A Visual C++ interface can be defined as follows:

  1. Can inherit from zero or more base interfaces.

  2. Cannot inherit from a base class.

  3. Can only contain public, pure virtual methods.

  4. Cannot contain constructors, destructors, or operators.

  5. Cannot contain static methods.

  6. Cannot contain data members; properties are allowed.

The syntax:

modifier __interface interface-name {interface-definition};

A C++ class or struct could be implemented with these rules, but __interface enforces them. For example, the following is a sample interface definition:

__interface IMyInterface {

   HRESULT CommitX();

   HRESULT get_X(BSTR* pbstrName);

};

Notice that you do not have to explicitly indicate that the CommitX() and get_X() functions are pure virtual. An equivalent declaration for the first function would be:

virtual HRESULT CommitX() = 0;

__interface implies the novtable __declspec modifier. The following sample shows how to use properties declared in an interface.

// __interface

#define _ATL_ATTRIBUTES 1

#include <atlbase.h>

#include <atlcom.h>

#include <string.h>

#include <comdef.h>

#include <stdio.h>

 

[module(name="test")];

 

[ object, uuid("00000000-0000-0000-0000-000000000001"), library_block ]

__interface IFace {

   [ id(0) ] int int_data;

   [ id(5) ] BSTR bstr_data;

};

 

[ coclass, uuid("00000000-0000-0000-0000-000000000002") ]

class MyClass : public IFace {

private:

    int m_i;

    BSTR m_bstr;

 

public:

    MyClass()

    {

        m_i = 0;

        m_bstr = 0;

    }

 

    ~MyClass()

    {

        if (m_bstr)

            ::SysFreeString(m_bstr);

    }

 

    int get_int_data()

    {

        return m_i;

    }

 

    void put_int_data(int _i)

    {

        m_i = _i;

    }

 

    BSTR get_bstr_data()

    {

        BSTR bstr = ::SysAllocString(m_bstr);

        return bstr;

    }

 

    void put_bstr_data(BSTR bstr)

    {

        if (m_bstr)

            ::SysFreeString(m_bstr);

        m_bstr = ::SysAllocString(bstr);

    }

};

 

int main()

{

    _bstr_t bstr("Testing");

    CoInitialize(NULL);

    CComObject<MyClass>* p;

    CComObject<MyClass>::CreateInstance(&p);

    p->int_data = 100;

    printf_s("p->int_data = %d\n", p->int_data);

    p->bstr_data = bstr;

    printf_s("bstr_data = %S\n", p->bstr_data);

}

 

Output:

 

p->int_data = 100

bstr_data = Testing

 

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

 


 

< Old To New C++ .Net version 1 | Main | Old To New C++ .Net version 3 >