I'm doing another C++/CLI project that involves porting some of my native C++ classes so that I can mix both native and managed code. And I'm hitting the same issues often enough to wonder about a few things about the C++/CLI language design.
One of the major changes from the old C++/CLI syntax to the new one is that you cannot have an unmanaged class member of a ref class.
e.g.
class U
{
...
};
ref class M
{
U u; // causes C4368: mixed types are not supported
};
This is because memory locations for instances of M can change, and there is a risk of using the address of u somewhere in unmanaged code after it has changed.
The workaround I've been using is to use U* u, and then use new/delete in the constructor/destructor, respectively. So far this has been a pretty mechanical process, but it also introduces additonal risk that I could leave a memory leak behind or delete things out of order in the destructor (in the native C++ version, some of my nested objects take references of one another).
I wonder if the language could have supported the original code (POD I think people called it) by treating U u as a hidden indirection (transparent to me). There should be enough information during construction to do the implicit new: if constructor arguments were needed for U, then any C++ syntax would give an error. The implicit delete might be a bit hairier.
Also, another change between the two Managed C++ versions is the introducution of ^ versus the ambiguous *, which was used to reference either an unmanaged type or a managed type. This seems to be a good thing, but I wish that I could be using the '.' notation rather that ->. It is cleaner and more intuitive since the managed ^ is more like an unmanaged & than an unmanged *. In many (or all ) cases where I accidentally use '.' instead, the compiler emits a warning and tells me that it's assuming ->. Why not restrict the -> operator to just pointers (*) and use '.' for handles
Brian

C++/CLI language design questions
Jeremy_AK
Thanks for the stack-based syntax. I forgot about that...
Brian
selwonk
Brandon Bray from the Visual C++ team has a detailed blog post motivating the design for mixed types:
http://blogs.msdn.com/branbray/archive/2005/07/20/441099.aspx
Also, C++/CLI supports stack-based syntax for managed types, so you can use the '.' notation:
http://msdn2.microsoft.com/en-us/library/ms177191.aspx
Thanks,
Mitch
byebyestar
(with vector<string>* columns)
for( size_t i = firstYCol; i < columns->size(); i++ )
{
(*columns)[ i ] = (*columns)[ i ] + "%";
}
The point being that I can't use some overloaded operators without first dereferencing as a parenthesized expression.
Also, during this conversion process, I'm not bothering to assert that these member pointers are non-null, because are too many of them (it is below my "should I assert this" threshold). I fall back on the assumption that constructors did new (which might be wrong in some cases), and that my destructor will not call dependent functions after delete.
Ryszard Kwiecinski - MSFT
I'm going to answer my own question on this one. After using the language for a while, I realize that -> is a better choice after all for at least two reasons.
1. If this is a handle, then this->method() matches standard C++ syntax.
2. -> is overloadable, which allows things like gcroot template to do its magic.
But I'm still curious about the possibility of using hidden indirection to enable unmanaged members inside managed members.