Re: "pointers" in /clr



beginthreadex wrote:

Persons that have been developing in VC++ for many years might run into the
same issues that I do with my teams. If MS knows that the classes are
collected then the syntax should not matter. There should be no reason for
^ instead of * or % instead of &. Just stick to what's already trained into
people so we don't need to keep rewritting things but use all the tools.

Unfortunately there are substantial differences between the native and the managed OOP paradigm. The .NET framework doesn't support global variables and functions at all, it only knows methods and properties. Although C++/CLI has stack syntax, the framework only supports pointer (handle) syntax for ref classes, and value classes are severely limited. In the managed world, there's no concept for const (in particular, global constants, const member functions), which is IMHO is a very big problem, but this is what we have. Heck, even the concept of destructors doesn't exist in the managed world, and C++/CLI destructors are not 100% compatible with the standard ones. The concept of default argument doesn't exist either. Should I go on? Virtual functions must be explicitly declared "override" if they override an existing one. There is no operator overloading either.


On the other hand, native C++ doesn't have the concept of properties, delegates, events, and most importantly, the concept of public and private classes. Every class that's #include'ed is public, what's not in the headers is private.

Even though it sounds nice in theory to be able to share the same code base between the native and the managed worlds, it's almost never technically possible. You can't write anything more than trivial that you could share between native C++ and managed C++. I agree that the old MC++ syntax looked like you could share trivial code between the two, but I don't think it was practical in real-world applications or libraries. You would have to be very careful to use only that narrow common feature set that both worlds have, and even then you have to deal with the class visibility issue. "public class" doesn't compile under std C++, but a simple "class" means private in old MC++, which is not what you want. The old MC++ syntax may give you a false sense of security that you can theoretically write code for both worlds, when in practice it almost never happens.

I question myself if it would have made sense to create C++/CLI so that you could share code between the two world. When you could really write it once and compile standard native C++ code into pure managed assemblies. Such as disregarding the const keyword in managed mode. Setting up the default class visibility using a #pragma class public, or something similar. Automatically inserting the "override" keyword for virtual methods that override existing ones. Keeping the * and & symbols for managed handles and references. Automatically substituting static const members with read-only properties. Automatically substituting default arguments with function overriding for .NET. Automatically substitute getter and setter functions with properties. And so on and so forth. But C++ is a low-level language, and these hidden translations in the background would certainly mean losing control. You still wouldn't be able to do everything, you'd still need to #ifdef a whole bunch of lines. You still wouldn't be able to use events in native C++ the exact same way as delegates work in .NET, even though similar concepts (boost::function) now exist in standard C++. It's impossible to translate every unmanaged C++ code to .NET anyway.

Quite frankly, I don't think this was their goal with C++/CLI. They wanted a language where you

1) have low-level, but full support for almost every .NET framework feature, with a language as similar to C++ as possible

2) can freely intermix managed and unmanaged code, and for that it was a very good idea to introduce the ^ and % symbols. It's way less confusing than __gc * and __nogc *. I love that T ^ is managed and U * is unmanaged, and I can tell that in an instant.

But I'm hearing you, sometimes it would be very nice to compile native C++ code into pure managed, without having to rewriting a single line, even if there are severe restrictions with that. Maybe someone will write a standard C++ to C++/CLI code converter. After all, Borland created a mechanism for automatically generating a C++ header file from a Pascal input, and with few limitations it works perfectly (only Pascal is trivial to parse, C++ is far from it). I can imagine an automated native to managed converter would work with restrictions, so we could write once and reuse the code twice. I could imagine converting boost::shared_ptr<T> to T^, and boost::function to delegates, and so on. The question is how much market it has, because it's quite some work to write such a compiler.

In practice, when you program for .NET you use framework types and functions, such as Drawing::Color, Rectangle, String, and .NET collections. How far are you willing to go with the automatic type substitution? I don't think it's feasable to really write your code once and reuse it for native C++ and .NET at the same time. You're pretty much forced to rewrite it, or to wrap unmanaged code into managed classes.

Tom
.



Relevant Pages

  • Re: a subtle change in behavior...
    ... syntax was not only changed, ... ref class derivedClassA: public baseClass ... > when derived classes can override functions they do not have permission to ... > 'internal' virtual functions (that is they are public inside the assembly ...
    (microsoft.public.dotnet.languages.vc)
  • Re: What Does this Mean?
    ... What is the purpose of: ... appears to override it with nothing. ... I don't know in what way you're confused about the *syntax* .... ... since the class you found implemented IHttpModule, ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Class.inherited v. inherited syntax inside Class
    ... method' syntax, e.g. UserClass.inherit. ... override that in a user defined class, you defined it with the same ... Whoops. ... 'inherit' --> 'inherited' ...
    (comp.lang.ruby)
  • Re: Destructor - ??
    ... in your override - thats why they force a different syntax and the compiler emits the call to base.Finalizeon commpilation. ...
    (microsoft.public.dotnet.framework)
  • Re: "pointers" in /clr
    ... > explicitly declared "override" if they override an existing one. ... > it once and compile standard native C++ code into pure managed ... Automatically substituting static ... > much forced to rewrite it, or to wrap unmanaged code into managed classes. ...
    (microsoft.public.dotnet.languages.vc)

Loading