You often want to provide two instances of an interface member within a class that implements the interface � one that is used when class objects are manipulated through an interface handle, and one that is used when class objects are used through the class interface. For example:
public __gc class R : public ICloneable { // to be used through ICloneable Object* ICloneable::Clone(); // to be used through an R R* Clone(); };
In Managed Extensions we do this by providing an explicit declaration of the interface method with the method's name qualified with the name of the interface. The class-specific instance is unqualified. This eliminates the need to downcast the return value of Clone, in this example, when explicit called through an instance of R.
In the new syntax, a general overriding mechanism has been introduced that replaces the Managed Extensions syntax. Our example would be rewritten as follows:
public ref class R : public ICloneable { public: // to be used through ICloneable virtual Object^ InterfaceClone() = ICloneable::Clone; // to be used through an R virtual R^ Clone(); };
This revision requires that the interface member being explicitly overridden be given a unique name within the class. Here, I've provided the awkward name of InterfaceClone. The behavior is still the same � an invocation through the ICloneable interface invokes the renamed InterfaceClone, while a call through an object of type R invokes the second Clone instance.
In Managed Extensions, the access level of a virtual function does not constrain its ability to be overridden within a derived class. In the new syntax, a virtual function cannot override a base class virtual function that it cannot access. For example:
__gc class Foo { // inaccessible to a derived class virtual void g(); }; __gc class Bar : public Foo { public: // in Managed Extensions, ok: g() overrides Foo::g() // in new syntax, error: cannot override: Foo::g() is inaccessible � void g(); };
There is no real mapping of this sort of design onto the new syntax. One simply has to make the base class members accessible � that is, non-private. The inherited methods do not have to bear the same access. In this example, the least invasive change is to make the Foo member protected. This way the general program's access to the method through Foo is still prohibited,
ref class Foo { protected: virtual void g(); }; ref class Bar : Foo { public: virtual void g() override; };
Note that the absence of the explicit virtual keyword in the base class, under the new syntax, generates a warning message.
Although static const integral members are still supported, their linkage attribute has changed. Their former linkage attribute is now carried in a literal integral member. For example, consider the following Managed Extensions class:
public __gc class Constants { public: static const int LOG_DEBUG = 4; };
This generates the following underlying CIL attributes for the field (note the literal attribute):
.field public static literal int32 modopt([Microsoft.VisualC]Microsoft.VisualC.IsConstModifier) STANDARD_CLIENT_PRX = int32(0x00000004)
While this still compiles under the new syntax:
public ref class Constants { public: static const int LOG_DEBUG = 4; };
it no longer emits the literal attribute, and therefore is not viewed as a constant by the CLR runtime:
.field public static int32 modopt([Microsoft.VisualC]Microsoft.VisualC.IsConstModifier) STANDARD_CLIENT_PRX = int32(0x00000004)
In order to have the same inter-language literal attribute, the declaration should be changed to the newly supported literal data member, as follows,
public ref class Constants { public: literal int LOG_DEBUG = 4; };