< Old To New C++ .Net version 2 | Main | Old To New C++ .Net version 4 >


 

 

Early Stages of the C++ .Net 25

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

 

 

 

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

  1. Managed Extensions for C++: __sealed keyword

  2. The new C++ sealed keyword

  3. The new C++ abstract keyword

 

Managed Extensions for C++: __sealed keyword

 

This topic applies only to version 1 of Managed Extensions for C++. This syntax should only be used to maintain version 1 code. Use sealed for the equivalent functionality in the new syntax. This keyword prevents a method from being overridden or a class from being a base class.

  1. __sealed class-specifier

  2. __sealed struct-specifier

  3. __sealed function-declarator

The __sealed keyword specifies that a class method cannot be overridden or that a class cannot be a base class. When using the __sealed keyword, keep the following points in mind:

  1. A __sealed virtual method cannot be overridden.

  2. If a nonvirtual member method is marked __sealed, the __sealed qualification is ignored.

  3. A __sealed method cannot be pure.

  4. The __sealed keyword is not allowed when used with the __interface keyword.

When a class (or struct) is marked with __sealed, the class cannot be used as a base class. For example:

__sealed __gc class A {

   // ...

};

// error: cannot derive from a sealed class

__gc class B : public A { /* ...*/ };

The __sealed keyword is not allowed when used with the __abstract keyword. In the following example, a sealed virtual method (f) is declared. The function is then overridden in main(), causing a compiler error:

// keyword __sealed

// compile with: /clr:oldSyntax

 

#using <mscorlib.dll>

extern "C" int printf_s(const char*, ...);

 

__gc struct I

{

    __sealed virtual void f()

    {

        printf_s("I::f()\n");

    }

    virtual void g()

    {

        printf_s("I::g()\n");

    }

};

 

__gc struct A : I

{

    void f() // C3248 sealed function

    {

        printf_s("A::f()\n");

    }

    void g()

    {

        printf_s("A::g()\n");

    }

};

 

int main()

{

    A* pA = new A;

 

    pA->f();

    pA->g();

}

The following is a sample output seen in the Visual C++ IDE's Output window.

1>------ Build started: Project: testprog2, Configuration: Debug Win32 ------

1>Compiling...

1>testprog2.cpp

1>.\testprog2.cpp(21) : error C3248: 'I::f': function declared as '__sealed' cannot be overridden by 'A::f'

1>        .\testprog2.cpp(9) : see declaration of 'I::f'

1>Build log was saved at "file://f:\vc2005project\testprog2\testprog2\Debug\BuildLog.htm"

1>testprog2 - 1 error(s), 0 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The new C++ sealed keyword

 

sealed is a context sensitive keyword that can indicate:

  1. A virtual member cannot be overridden.

  2. A type cannot be used as a base type.

sealed is also valid when compiling for native targets (without /clr). You can detect at compile time if a type is sealed with __is_sealed (type). sealed is a context-sensitive keyword. This sample shows the effect of sealed on a virtual member:

// sealed keyword

// compile with: /clr

interface struct I1 {

   virtual void f();

   virtual void g();

};

 

ref class X : I1 {

public:

   virtual void f() { System::Console::WriteLine("X::f override of I1::f"); }

   virtual void g() sealed { System::Console::WriteLine("X::f override of I1::g"); }

};

 

ref class Y : public X {

public:

   virtual void f() override { System::Console::WriteLine("Y::f override of I1::f"); }

   /*

   // the following override generates a compiler error

   virtual void g() override {

      System::Console::WriteLine("Y::g override of I1::g");

   } 

   */

};

 

int main() {

   I1 ^ MyI = gcnew X;

   MyI -> f();

   MyI -> g();

 

   I1 ^ MyI2 = gcnew Y;

   MyI2 -> f();

}

 

Output:

ref class, virtual and sealed keywords program output

 

The following sample shows how to mark a class as sealed:

// sealed keyword

// compile with: /clr

interface struct I1 {

   virtual void f();

};

 

ref class X sealed : I1 {

public:

   virtual void f() override {}

};

 

ref class Y : public X {   // C3246 base class X is sealed

public:

   virtual void f() override {}

};

The following is the output sample seen in the Output window.

1>------ Build started: Project: cplus, Configuration: Debug Win32 ------

1>Compiling...

1>cplusrc.cpp

1>.\cplusrc.cpp(9) : warning C4490: 'override' : incorrect use of override specifier; 'X::f' does not match a base ref class method

1>        'new' or 'override' are only allowed when a matching base method from a ref class exists

1>        Matching base method 'I1::f' is from an interface class (not a ref class)

1>.\cplusrc.cpp(12) : error C3246: 'Y' : cannot inherit from 'X' as it has been declared as 'sealed'

1>        .\cplusrc.cpp(7) : see declaration of 'X'

1>Build log was saved at "file://f:\vc2005project\cplus\cplus\Debug\BuildLog.htm"

1>cplus - 1 error(s), 1 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The new C++ abstract keyword

 

abstract is a context sensitive keyword that can indicate:

  1. A member can only be defined in a derived type.

  2. A type cannot be instantiated (can only act as a base type).

Marking a function abstract is the same as making it a pure virtual function. Making a member function abstract causes the enclosing class to also be marked abstract. abstract is also valid when compiling for native targets (without /clr). You can detect at compile time if a type is abstract with __is_abstract(type). abstract is a context-sensitive keyword. The following sample will generate an error because class X is marked abstract.

// abstract keyword

// compile with: /clr

ref class X abstract

{

public:

   virtual void f() {}

};

 

int main()

{

   X ^ MyX = gcnew X;   // C3622 cannot instantiate abstract class

}

The following is an output sample seen in the Output window.

 

1>------ Build started: Project: cplus, Configuration: Debug Win32 ------

1>Compiling...

1>cplusrc.cpp

1>.\cplusrc.cpp(9) : error C3622: 'X': a class declared as 'abstract' cannot be instantiated

1>        .\cplusrc.cpp(3) : see declaration of 'X'

1>Build log was saved at "file://f:\vc2005project\cplus\cplus\Debug\BuildLog.htm"

1>cplus - 1 error(s), 0 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The following sample shows that the compiler will generate an error because a native class is marked abstract, when compiled with /clr.

// abstract keyword

class X abstract

{

public:

   virtual void f() {}

};

 

int main()

{

   X * MyX = new X;   // C3622 error expected

}

The following is the output sample seen in the Output window.

1>------ Build started: Project: cplus, Configuration: Debug Win32 ------

1>Compiling...

1>cplusrc.cpp

1>.\cplusrc.cpp(8) : error C3622: 'X': a class declared as 'abstract' cannot be instantiated

1>        .\cplusrc.cpp(2) : see declaration of 'X'

1>Build log was saved at "file://f:\vc2005project\cplus\cplus\Debug\BuildLog.htm"

1>cplus - 1 error(s), 0 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The following sample will generate an error because function f is marked abstract.

// abstract keyword

// compile with: /clr

ref class X {

public:

   virtual void f() abstract {}   // C3634 error expected

   virtual void g() = 0 {}   // C3634 error expected

};

The following is the output sample seen in the Output window.

1>------ Build started: Project: cplus, Configuration: Debug Win32 ------

1>Compiling...

1>cplusrc.cpp

1>.\cplusrc.cpp(5) : error C3634: 'void X::f(void)' : cannot define an abstract method of a managed class

1>.\cplusrc.cpp(6) : error C3634: 'void X::g(void)' : cannot define an abstract method of a managed class

1>.\cplusrc.cpp(3) : warning C4570: 'X' : is not explicitly declared as abstract but has abstract functions

1>        'void X::f(void)' : is abstract

1>        .\cplusrc.cpp(5) : see declaration of 'X::f'

1>        'void X::g(void)' : is abstract

1>        .\cplusrc.cpp(6) : see declaration of 'X::g'

1>Build log was saved at "file://f:\vc2005project\cplus\cplus\Debug\BuildLog.htm"

1>cplus - 2 error(s), 1 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

 

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

 


 

< Old To New C++ .Net version 2 | Main | Old To New C++ .Net version 4 >