I have an object class that needs to access component-like pieces from a "manager" class. (To shrink getSystem()->getInput()->getKey() etc... Basically rid of lengthy tags. )
Unfortunately, the class is not aware of the manager and cannot access it's components directly. SO, to wrap around this, I've designed this code:
[heading]Object Code snippet:[/heading]
Object.h
// Forward declare the manager
class Manager; // Stores components and other various materials
// Derive DeviceImpl later for real usage.
// This is just as a temp placement since
// Manager is currently inaccessible.
class DeviceImpl
{
private:
public:
DeviceImpl() { ; }
virtual ~DeviceImpl() { ; }
template <typename Device>
Device *getDevice()
{
std::cout << "DeviceImpl returning null in getDevice" << std::endl;
return 0;
}
};
class Object
{
private:
friend Manager;
DeviceImpl *device_impl;
void setDevice(DeviceImpl *device)
{
std::cout << "Object: adding device" << std::endl;
device_impl = device;
}
public:
template<typename Device> Device *getDevice()
{ return device_impl->getDevice<Device>();}
Object() { device_impl = 0; }
~Object() { ; }
};
[heading]Manager code snippets[/heading]
Manager.h
#include "Object.h" // Manager stores series of objects and updates them
class DeviceHandler;
class Manager
{
private:
Graphics *graphics;
Input *input;
Factory *factory;
Camera *camera;
Map *map;
DeviceImpl *device;
public:
Graphics *getGraphics();
Input *getInput();
Factory *getFactory();
Camera *getCamera();
Map *getMap();
void Manager::addObject(Object *newObject)
{
// If null, stop function
if (!newObject)
return;
// Clamp entity data into a shared pointer
boost::shared_ptr<Object> temp(newObject);
// Add the manager
temp->setDevice(device);
// Initialize
temp->init();
// Push back onto the list
vObjects.push_back(temp);
}
Manager();
~Manager();
};
/*
Now define the DeviceHandler because manager is defined
*/
class DeviceHandler : public DeviceImpl
{
private:
Manager *manager;
public:
DeviceHandler(Manager *m) : DeviceImpl()
{ manager = m; std::cout << "Manager set" << std::endl; }
template <typename Device>
Device *getDevice()
{
std::cout << "Getting a device..." << std::endl;
if(!manager)
{
std::cout << "returning null" << std::endl;
return 0;
}
Device* deviceTypeTest = 0;
if( (deviceTypeTest = dynamic_cast<Graphics*>(deviceTypeTest) != 0) )
{
std::cout << "returning graphics" << std::endl;
return manager->getGraphics();
}
else if( (deviceTypeTest = dynamic_cast<Input*>(deviceTypeTest) != 0) )
{
std::cout << "returning input" << std::endl;
return manager->getInput();
}
else if( (deviceTypeTest = dynamic_cast<Camera*>(deviceTypeTest) != 0) )
{
std::cout << "returning camera" << std::endl;
return manager->getCamera();
}
else if( (deviceTypeTest = dynamic_cast<Map*>(deviceTypeTest) != 0) )
{
std::cout << "returning Map" << std::endl;
return manager->getMap();
}
else if( (deviceTypeTest = dynamic_cast<Factory*>(deviceTypeTest) != 0) )
{
std::cout << "returning factory" << std::endl;
return manager->getFactory();
}
else if( (deviceTypeTest = dynamic_cast<Manager*>(deviceTypeTest) != 0) )
{
std::cout << "returning manager" << std::endl;
return manager;
}
std::cout << "returning null" << std::endl;
return 0;
}
};
Manager.cpp
// ... Lots of other important stuff but finally define the constructor and deconstructor
//Ctors and dtors
Manager::Manager()
{
device = new DeviceHandler(this);
// Lots mo stuff
}
Manager::~Manager() { ; }
[heading]Example of usage[/heading]
class Ball : public Object
{
private:
Sprite ball;
// ... Basic initialize stuff
public:
// Draw routine
void draw()
{
std::cout << "Ball: Drawing. Getting graphics." << std::endl;
getDevice<Graphics>()->draw(ball, getX(), getY());
{
// Some Mo' stuff...
};
[heading]Problem[/heading]
Now this all compiles fine and runs! But it does not seem to ever seem to refer to getDevice() in DeviceHandler. Instead, it still seems to use DeviceImpl.
[heading]Output:[/heading]
Manager set
Object: adding device
Ball : Drawing. Getting graphics.
DeviceImpl returning null in getDevice.
[heading]This is where you help[/heading]
Perhaps it's a logic error that I'm missing or even a better design would be helpful. So to you future people: thanks!