MC++ problem with virtual function overrides and collection editor

E

Edward Diener

In C++ an overridden virtual function in a derived class must have the exact
same signature of the function which is overridden in the base class, except
for the return type which may return a pointer or reference to a derived
type of the base class's return type.

In .NET the overridden virtual function is similar, but an actual parameter
of the function can be a derived reference from the base class's reference
also.

This dichotomy can create a problem when using MC++ to override virtual
properties. In MC++ one can never override a virtual property by using a
derived reference type for the base class's reference type. In .NET one can
specify an overridden property which is a derived reference type from the
base class's reference type.

This dichotomy comes into play when creating a custom collection class in
MC++. The typical custom collection in other .NET languages overrides the
Item type in CollectionBase, not only to provide type-safe usage but to
creating a more specific type than an 'object' reference which the
collection editor in the Component Designer and Windows Form Designer will
understand to allow specific types to be added to a collection.

In MC++, however, it appears that the Item type must still be the 'object'
reference ( Object * in MC++ ) since it is impossible to override the
set_Item function with a different type than an Object * because of
paragraph 1 above. This means that because the get_Item and set_Item must
refer to the same type, the type must be Object * for an MC++ custom
collection class. Of course MC++ can still provide type-safe usage by not
allowing anything but the actual Item object, whatever it is, to be added,
inserted, and removed from the collection. However as far as the collection
editor in the Component Designer and Windows Form Designer is concerned, any
object is a possibility to be added to such a collection.

Is there a way around this difference between MC++ other .NET languages
other than writing one's collections in another .NET language and creating a
separate assembly just for the collection, or accepting the limitation of
MC++ as far as the collection editor is concerned ?
 
B

Bart Jacobs

Edward,

The .NET Framework 1.1 SDK documentation topic for class CollectionBase
includes a C++ sample, and this sample does compile and run correctly on
the .NET Framework 1.1.

This example does not compile with the C++ compiler that comes with the
..NET Framework 1.0 SDK, however. If I understand correctly, two
differences between VC++ 7.0 and VC++ 7.1 are at play here:
- If a __gc class declares a method whose name and parameter list match
an interface method, then VC++ 7.0 assumes that the programmer wants to
implement the interface method and, thus, requires that the return type
is covariant. VC++ 7.1, however, does not assume this. If the return
type is not covariant, VC++ 7.1 considers both methods to be unrelated.
- If a __gc class declares two methods with the same name and parameter
types, then VC++ 7.0 requires that they are both qualified with an
interface name. VC++ 7.1, however, allows one method to be unqualified.

In short, VC++ 7.0 behaves more like C++ and VC++ 7.1 behaves more like C#.

Your analysis contains some errors. See below.

Edward said:
In C++ an overridden virtual function in a derived class must have the exact
same signature of the function which is overridden in the base class, except
for the return type which may return a pointer or reference to a derived
type of the base class's return type.

I agree.
In .NET the overridden virtual function is similar, but an actual parameter
of the function can be a derived reference from the base class's reference
also.

I believe that, for all intents and purposes, this statement is false,
and that in .NET, a method m1 overrides a method m2 only if the
parameter types list and the return type of m1 are equal to those of m2.
In this case, .NET is more strict than C++, and not the other way
around. My belief is supported by all known current implementations, as
well as by the C# Language Specification, which says, in section 10.5.4:
"An override method overrides an inherited virtual method with the same
signature." The same section also says that it is an error if the
override declaration and the overridden base method do not have the same
return type. Interestingly, I was not able to find language in the
Common Language Infrastructure (CLI) specification that supports either
of our views. The CLI says that the callvirt instruction calls the
method that "matches" the name and signature specified in the
instruction. Note that in CLI terminology, the signature includes the
return type. The problem is that "to match" could be interpreted as "to
equal", but it could also be interpreted as allowing covariance.

This is very interesting food for language lawyers, but a more relevant
point is that creating a strongly typed collection class using
CollectionBase does not require covariance.

For example: Please see the Int16Collection example in the 1.1
documentation for CollectionBase. The set_Item(int,Int16) method does
not override the set_Item(int,object) method. These two methods are
unrelated. The Int16Collection class serves its purpose as a strongly
typed collection class, even in the absence of covariance.
This dichotomy can create a problem when using MC++ to override virtual
properties. In MC++ one can never override a virtual property by using a
derived reference type for the base class's reference type. In .NET one can
specify an overridden property which is a derived reference type from the
base class's reference type.

Sentence 2 is true; sentence 3 is false.
This dichotomy comes into play when creating a custom collection class in
MC++. The typical custom collection in other .NET languages overrides the
Item type in CollectionBase, not only to provide type-safe usage but to
creating a more specific type than an 'object' reference which the
collection editor in the Component Designer and Windows Form Designer will
understand to allow specific types to be added to a collection.

Custom collection classes declare an Item property, and this property is
retrieved through reflection by the Designers, but this property does
not override the Item property declared by IList.
In MC++, however, it appears that the Item type must still be the 'object'
reference ( Object * in MC++ ) since it is impossible to override the
set_Item function with a different type than an Object * because of
paragraph 1 above. This means that because the get_Item and set_Item must
refer to the same type, the type must be Object * for an MC++ custom
collection class.

The point is that VC++ 7.0 does not allow a function declaration whose
name and parameter types list are equal to a function in a base type,
except if the declared function overrides the function in the base type.
VC++ 7.1 does allow this (for __gc classes at least).
Is there a way around this difference between MC++ other .NET languages
other than writing one's collections in another .NET language and creating a
separate assembly just for the collection, or accepting the limitation of
MC++ as far as the collection editor is concerned ?

I do not think it is possible in VC++ 7.0.

Greetings

Bart Jacobs
 
E

Edward Diener

Bart said:
Edward,

The .NET Framework 1.1 SDK documentation topic for class
CollectionBase includes a C++ sample, and this sample does compile
and run correctly on the .NET Framework 1.1.

This example does not compile with the C++ compiler that comes with
the .NET Framework 1.0 SDK, however. If I understand correctly, two
differences between VC++ 7.0 and VC++ 7.1 are at play here:
- If a __gc class declares a method whose name and parameter list
match
an interface method, then VC++ 7.0 assumes that the programmer wants
to implement the interface method and, thus, requires that the return
type
is covariant. VC++ 7.1, however, does not assume this. If the return
type is not covariant, VC++ 7.1 considers both methods to be
unrelated. - If a __gc class declares two methods with the same name
and parameter types, then VC++ 7.0 requires that they are both
qualified with an interface name. VC++ 7.1, however, allows one
method to be unqualified.

In short, VC++ 7.0 behaves more like C++ and VC++ 7.1 behaves more
like C#.

Thanks for this elucidation.
Your analysis contains some errors. See below.



I agree.


I believe that, for all intents and purposes, this statement is false,

You are correct and it is my error in thinking so.
snipped...

Custom collection classes declare an Item property, and this property
is retrieved through reflection by the Designers, but this property
does
not override the Item property declared by IList.

This is what led to my wrong thinking and misunderstanding of virtual
function overrides in .NET. I had assumed that the implementations of custom
collection classes were overriding virtual functions in the base
CollectionBase class, without closing looking at the code in the examples or
even noticing that there was a version for MC++ using Int16. They are
actually overloading functionality, using covariant parameter and return
types, and not overriding them. I hadn't made the association that
reflection was at work in the Collection Editor of the Windows Form Designer
and Component Designer rather than normal polymorphism, but there was no
documentation that this was happening. So I naively assumed that .NET
allowed co-variant parameters as well as covariant return types in its
overrides, which was the only way I could think of that custom collection
classes would work at design time. Evidently the Collection Editor assumes
common property and member function names for a custom collection class but
adjusts to the covariant parameters and/or return types for those names
through reflection. In that case, creating a type-safe class in MC++ works
fine, at least with the VC++ 7.1 compiler, without having to resort to
'object' being the common type in all properties and member functions.
The point is that VC++ 7.0 does not allow a function declaration whose
name and parameter types list are equal to a function in a base type,
except if the declared function overrides the function in the base
type. VC++ 7.1 does allow this (for __gc classes at least).

Yes that would force one in .NET 2002 to override, rather than overload,
CollectionBase properties and methods. But I think that there are notes in
the CollectionBase doc pointing out that certain functionality is not
supported in the 1.0 framework.
I do not think it is possible in VC++ 7.0.

Thanks for all the information and for correcting my false impression of how
the Collection Editor worked with custom collection types.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top