|
Just a while ago, an ongoing search turned up the System::Activator class, but it will be some time before I can put together a test situation, working with the other difficulties we are confronted with. If anyone else is interested, here's a link to the Activator class topic:
http://msdn2.microsoft.com/en-us/library/system.activator.aspx
I think this will work, but any further ideas appreciated, especially proven techniques.
Much thanks,
mike
|
|
|
|
|
Try this. Assuming you have a class Blah and you want to instantiate an instance of it
namespace MyNameSpace
{
public ref class Blah
{
public:
Blah()
{
}
};
}
void SomeOtherMethod()
{
//assumes class Blah has a constructor with no arguments
//note the use of c# style of specifying namespaces with . and not ::
System::String ^ className = gcnew System::String("MyNameSpace.Blah");
System::Type ^ aType = System::Type::GetType(className);
System::Reflection::ConstructorInfo ^aC = aType->GetConstructor(gcnew array<System::Type^>(0));
System::Object ^ aBlah = aC->Invoke(gcnew array<System::Object^>(0));
aBlah is now an instance of Blah but needs to be casted
}
Not sure if this is exactly what you want but its a start
|
|
|
|
|
|
After studying this, I would have serious problems with the need to cast aBlah, if this would force us (or clients) to deploy casting parameters.
Of course, as MyClass is the base class for all legal descendants to be constructed by the factory method, we could possibly eliminate our needs to cast by trying something like this with your code:
OurNameSpaces::MyClass ^ aBlah = aC->Invoke(gcnew array<system::object^>(0));
That may fix things for us, but it may convolute things for clients wanting to process their own descendants of MyClass if they are still forced to cast when our code creates instances of MyClassDescendants for them.
As it appears that your skills are quite firm (cheers), I'm curious about your assertion that there will be a need to cast when it appears your snippet coerces a call to the desired constructor. The factory method we need to translate from Delphi/CPPB generates the usual MyClass instances for clients, but allows them to declare and define their own MyClassDescendants, and, without deriving from the factory object or having to install a custom factory object descendant in the IDE, our factory object class creates and manages their needed, various descendants of MyClass for them. In fact, the factory will dynamically, alternatively create any different descendant, simply by passing the class reference parameter (this is the whole purpose of such factory methods).
Because these are the purposes, if we construct their descendants as OurNameSpaces::MyClass, we will want them not to have to cast to MyClassDescendants to perform their own processing of their MyClassDescendants instances.
We're brand new to managed C++, these libraries, and the VS compiler, but it seems that what we really want to be able to do is call either our constructor (for base class instances generated by the factory) or the client's constructor (for client descendants to be generated by the factory). That would seem to mean that we cannot eliminate *our* need to cast by the approach, OurNameSpaces::MyClass ^ aBlah = aC->Invoke(gcnew array<system::object^>(0)), because client MyClass descendant constructors may be written outside of our namespaces. I'm just thinking out loud, but it seems that the concern to accommodate the client in turn means that we would have to preserve the System::Object aspect of your approach, which would mean that both client code and our code are back to having to cast.
In the MSDN example for System::Activator (http://msdn2.microsoft.com/en-us/library/system.activator.aspx), the (VB example source) approach is a bit different:
Dim o As Object = Activator.CreateInstance(GetType(StringBuilder))
I have to build quite a library of classes before I can test either approach under real conditions, so it will be a while before we know if the latter will avoid the need to cast. But again, thanks for the starting point (which may be much more than that).
|
|
|
|
|
mmontagne wrote: if they are still forced to cast when our code creates instances of MyClassDescendants for them.
I don't understand. If you have a factory that returns a "base" class how do you access extended attributes of the derived type without casting to the derived type?
led mike
|
|
|
|
|
That's the way it works with Delphi/CPPB class references -- which is desirable for the purposes, and what I'm hoping to emulate/replicate in managed C++.
When you assign the class identifier (name) of a derived class to a class reference and pass the class reference to a factory method, it calls the constructor of the derived class and constructs an instance of the derived class which does not have to be cast. Of course, as the derived class inherits the members of the base class, it is also safe to call the methods of the base class in the derived class instances.
So this capability is exceedingly simple and clean. All you have to do is declare a class reference type, and variables/arguments of this class reference type. The class names/identifiers of the base type and all of its descendants are legal values to assign to the class reference variables or arguments. Your factory method simply takes a class reference and calls the proper constructor.
So for instance (in Delphi syntax), here is one valuable way to implement class references in a factory object:
MyBaseClassReferenceType = class of MyBaseClass; // Type/class definition (complete).
// The following is a field declared in TMyFactoryObject base class, which orients all (similar) methods to any focused FactoryCreationClass descendant:
FFactoryCreationClass: MyBaseClassReferenceType; // Member variable/field. In Delphi, instance types are declared after a colon, which is preceded by the reference (pointer) name.
// "class" methods are roughly the equivalent of static functions of C++. This one "class"/static method instance thus is shared by all TMyFactoryObject instances and descendants, but returns the desired, constructed FactoryCreationClass instance to the calling TMyFactoryObject (as intended):
class function TMyFactoryObject.CreateBaseOrAnyDescendantFactory(TMyFactoryObject: FactoryObjectInstance): MyBaseClassReferenceType; // Return types, in Delphi, are declared after the method signature.
begin
Result := FactoryObjectInstance.FFactoryCreationClass.CommonConstructorName(ArgumentsRequiredByFactoryCreationClass);
end;
This of course is powerful, fast (it's all inherently pointer based), and produces exceedingly light footprints.
So, I understand why you would ask the question, as this does not fit cleanly within the pattern of ANSI C++, because when we call the constructor of the base class name (which has a different identifer/name, versus the shared name of overridden constructors in Delphi) this will only create the parts of the base class. Here, what's happening is the constructor of the intended descendant is indeed called (which inherits the same name, "Create", of the constructor of the base). The nomenclature indicates this descendant constructor (or the base constructor, if the base class is assigned to FFactoryCreationClass). Thus, a descendant instance is returned which does not require casting.
Hmmmm... now that we think of it, probably this ambiguous identification of the necessary constructor explains the need for said Activator class, eh?
-- modified at 16:01 Friday 29th September, 2006
|
|
|
|
|
mmontagne wrote: When you assign the class identifier (name) of a derived class to a class reference and pass the class reference to a factory method, it calls the constructor of the derived class and constructs an instance of the derived class which does not have to be cast.
That sounds like you're asking for a "virtual constuctor", which does not exist in C++. The types of objects being constructed have to be known at compile time. Google for "virtual constuctor" and you'll see some ways of hand-rolling this.
|
|
|
|
|
Thanks Mike,
However, it's not really, simply a virtual constructor issue, even in Delphi or C++ Builder.
I'm aware both that we have no virtual constructors, and that we cannot call virtual methods from constructors. The nature of the constructors is not really the issue. The real issue is identifying the proper constructor of an unknown class from its class identifier. Here's the bare gist of what we need to do, expressed a bit differently:
We have a control which parents further controls of different types. Clients may populate this control with one type, with many types, and even with their own custom descendants of our base child types. Our root, composite component generates instances of these children, manages the spatial distribution and focusing of the children, routes calls to the focused child, and automates their destruction.
Clients/users may want to descend from the basic types which the original control manages; and we must also provide means for them to elect to create any one particular type (at a time) of the basic types which the control manages. This capability must be supported even at design time, in the development environment.
Because we cannot know what yet-to-exist descendants the clients of our control suite may derive from our base child classes, the necessary solution parallels our Delphi implementation, where the client can pass their class identifier (class reference) to our root control, from which our root control can identify and call the proper constructor of their descendant. Editors allow them to do this at design time, so that they do not even have to install their class/components in the IDE (which eliminates substantial work and technical difficulty for them).
The critical issue therefore is that we have to link a class identifier to the proper constructor for child classes which may not even exist at the time we produce our root component. Presently, we use a real class identifier (Delphi/CPPB "Class Reference") which is intrinsically associated with the constructor of the class; because, in Delphi/CPPB, we can call the proper constructor directly, because *it is* the default constructor of the class identifier.
But you have me thinking here. I suppose we could take a string identifier and constructor fields of a struct as our former argument, thus explicitly identifying the constructor to call -- although I don't know what issues might exist for supporting this valuable behavior at design time in VS. In other words, how would we store handles of constructors of client descendants in a collection property, so that they could be called at run time or design time?
|
|
|
|
|
PS.
All this (except how to store or manage class identifier *properties*) may be moot however, if the Activator class provides the needed services.
|
|
|
|
|
mmontagne wrote: But again, thanks for the starting point (which may be much more than that).
You're very welcome. Have you thought about combining the code above with a template to hide the cast and present a nice interface to users of your code?
|
|
|
|
|
Good suggestion. I'm not sure the Activator needs to be handled that way, but in either case, if there is an opportunity to build a generic/template, that is certainly how to approach this.
Where we are really stuck for the moment (we're new to VS) is component development references. We have a book on order, but have some steep issues which require that we know much more about classes and how their properties are registered/supported in the IDE than we're finding bundled/linked documentation for. Any suggestions for top quality references appreciated. The book we're looking at is "Programming .NET Components, 2nd Edition," by Juval Lowy. It's C# oriented, but we're hoping that the approaches/examples will be conducive to managed C++, if that will be preferrable for us. Otherwise, we'll have to look at doing these projects in C#. For the moment (until this book gets here and we have it under our belt), things are on hold.
Actually, we're doing a final release build in Delphi as we get ready for a serious VS push.
|
|
|
|
|
mike montagne wrote: Otherwise, we'll have to look at doing these projects in C#.
I dont see a huge advantage in managed c++ over c#. We have a lot of unmanaged c++ code that we would like to use from c# clients so I have been investigating using managed c++ to make wrapper classes for our existing libraries. It looks like we're going to go down this path and my next big challenge is to see how much of this we can generate.
Unless you think you can reuse a lot of the code from your Delhpi perhaps c# would be a good option.
I dont have any specific book recomendations. I would look for something that addresses the run time more than a particular language.
|
|
|
|
|
Thanks much for the advice. We're trying to weigh all this with an open mind. One thing we have been interested in (for our own style of doing things) is being able to run native code. That's a C++ thing. But if we can run C# components in native C++ implementations, the broad acceptance of C# as a more expedient tool has major influence on our own disposition. I suppose this book is going to be a hinge point.
|
|
|
|
|
I have a class that implements System::Collections::Generic::IEnumerable<> interface. System::Collections::Generic::IEnumerable<> is derived from System::Collections::IEnumerable and both have a pure virtual method called GetEnumerator() but with different return types.
To over come the "overloaded function differs only by return type" error I used an 'explicit override' as described in the documentation. The code looks like this....
virtual System::Collections::Generic::IEnumerator<OptiverAu::VaultDotNet::TradeDelta^>^ GetEnumerator()
{
//to be implemented
return nullptr;
}
//note the '= blah blah' (this is the expicit override)
virtual System::Collections::IEnumerator ^ GetEnumeratorNG() sealed = System::Collections::IEnumerable::GetEnumerator
{
return GetEnumerator();
}
Seems a wierd way of doing things but it works. Now I want to write a class that implements the System::Collections::Generic::IEnumerator<> generic interface to be returned from the GetEnumerator() function above
System::Collections::Generic::IEnumerator is derived from System::Collections::IEnumerator in the same way as the example above. Both have a 'pure virtual' property called Current but with different return types.
What is the syntax for an explicit override of a property? I have spent an entire day searching and cant find the answer anywhere.
|
|
|
|
|
You override the get and set and not the property itself
interface class IFoo
{
property int Count
{
int get();
void set(int);
}
};
ref class Foo : IFoo
{
public:
Foo() : m_count(1) {}
property int Size
{
virtual int get() = IFoo::Count::get
{
return m_count;
}
virtual void set(int value) = IFoo::Count::set
{
m_count = value;
}
}
private:
int m_count;
};
|
|
|
|
|
Thanks you VERY much. I tried just about every combination except renaming the property and putting the expicit override on the get() & set().
|
|
|
|
|
Hello,
How to call CoGetInterfaceAndReleaseStream(…) in a secondary thread in managed VC++.NET 2003 application? I can successfully call CoMarshalInterThreadInterfaceInStream(…) in the main thread. After that in the secondary thread I call CoInitialize(NULL) with S_OK result, but CoGetInterfaceAndReleaseStream(…) returns -2147352568 error code.
Please help!!!!!!!!
Regards,
Leonid
|
|
|
|
|
Hi friends,
Can anyone tell me what will be the output of the folloing code and whats the reason for that.
It will be a great help.
<br />
int x = 12;<br />
int y = 6;<br />
x = x++ + y++<br />
cout<<x<<endl<<y;<br />
can you tell me the output for C++ and Java compiler and whats the reason for the answer.
Thanks in Advance
Sushant Duggal.
|
|
|
|
|
Sushant Duggal wrote: can you tell me the output for C++ and Java compiler and whats the reason for the answer.
Yes I can... but then I would be doing your class assignment for you.
led mike
|
|
|
|
|
Sushant Duggal wrote: cout<<x<<endl<<y;< blockquote="">
This code is making some assumptions that are now being shown for it to compile as C++. It's not going to compile for Java.
Beyond that, I agree with the other reply, you need to do your own homework.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
Thanks for your reply friends,
But I just want to know the reason why the outputs differ.
i
In C++, The result is x=18.y=7
where as in Java, The result is x=19, and y=7
I want to know the reason for this output.
Is there a difference of stack implementation in the two languages or there is some other reason..
Please let me know.
Thanks,
Sushant Duggal.
|
|
|
|
|
++x guarentees that the number is incremented before it's returned. x++ guarentees it's incremented after, but not how LONG after.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
Yes, I agree on your comment.
so do you want to say that there is no method to determine the value?
Sushant Duggal.
|
|
|
|
|
OK
now i got the point.
its correct to get 19 in C++,
but I still didnt understand why it comes 18 in java.
Can you comment on this?
Thanks
Sushant Duggal.
|
|
|
|
|
I believe it goes like this:
The ++ operator occurs in both languages AFTER x is given it's final value. The difference is that in Java, the values are by reference, so the value that x is assigned to, is the value that still has a ++ operator outstanding. so, x gets set to 18. y gets incremented, to 7, and x also gets incremented, but it's the same x that is 18, not a copy of x which is 16.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|