I'm using a (apparently) interesting approach for the problem.
I need to keep track of a lot of objects for a vessel. Sometimes the objects are not needed (VC cockpit) and can be deleted for saving resources (mainly, processor time), but should be recreated after.
So, my constructors have only one parameters: the container handle or a Info struct where the parameters are.
Code:
MyVessel::MyVessel()
: controller(new Controller(getHandle())
{
}
void MyVessel::cblkSetVesselCaps() // or something like that
{
CrewInfo info;
info.parm1 = "blah";
info.parm2 = 1919;
info.parm3 = E_TYPE_CAPT;
this->controller.Register(info);
info.parm3 = E_TYPE_SCI;
this->sci = this->controller.Register(info);
// and so on
}
I'm using "this->" to make it clear what are local variables and what are instance's properties.
The Register function is defined as "void Register(ControlInfo const &info)", and is overloaded for each kind "managed class" (each class has its Info struct);
For objects that are "static", i.e., they are to be keep alive while the vessel is alive, the Register feeds the struct into the Constructor, put the object in a "destruction time destroy list", and returns the pointer.
Things became interesting on objetcs that must be kept alive only in certain circustances, as when the vessel has the focus:
Code:
class Controller {
void RegisterForFocus(FocusObjectInfo const & info, UINT const oid);
operator FocusObject*() {return this->focusObjectArray.data();};
void HandleFocusGained();
void HandleFocusLost();
}
void MyVessel::ExampleOfUse() {
FocusObjectInfo info = {blablabla, blabalbla};
this->controller.RegisterForFocus(info, OID_SOME_RANDOM_OBJECT);
FocusObject* fo = controller;
fo[OID_SOME_RANDOM_OBJECT].doSomething(with, this);
}
Again, the Register will be overloaded for every different class.
The Register will make a *COPY* of the info struct, and keep it in list<FocusObjectInfo>. It's important to make a copy, as this parameter will be commonly came from a stack memory. It will not return any pointer, as the object will be created only when the vessel gets the Focus.
The
operator <type>() was created to get access to the current instance of the object (as it is constantly destroyed and recreated). You must %define a OID for each instance of your objects. I made no provisions for arrays of objects. See below how to use this (clever trick, uh?)
So, by monitoring , you :
Code:
void MyVessel::clbkFocusChanged(bool getfocus, OBJHANDLE hNewVessel, OBJHANDLE hOldVessel) {
if (getfocus || hNewVessel == this->GetHandle()) this->controller.HandleFocusGained();
else if (!getfocus || hOldVessel == this->GetHandle()) this->controller.HandleFocusLost();
YourRemainingStuff();
}
And you can destroy and recreate everything easily.
That operator trick is kinky, but it works. Below a example made in VS2010 (it compiles and works as expected!)
Code:
// Tests.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include <array>
class Controller {
private:
std::array<std::string,10> stringArray;
std::array<int,10> intArray;
public:
void Register(std::string const & info, int const oid)
{
stringArray[oid] = info;
};
operator std::string*() {return this->stringArray.data();};
void Register(int const & info, int const oid)
{
intArray[oid] = info;
};
operator int*() {return this->intArray.data();};
};
int _tmain(int argc, _TCHAR* argv[])
{
Controller c;
c.Register("000", 0);
c.Register("001", 1);
c.Register(1000, 0);
c.Register(50000, 1);
std::string *s = c;
int *i = c;
printf("%s %s\n", s[0].c_str(), s[1].c_str());
printf("%d %d\n", i[0], i[1]);
}