Jump to content
  • Advertisement
Sign in to follow this  
GanonPhantom

Dynamic Object Factory

This topic is 3780 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Im building my very own Dynamic (or plugin-able) Object Factory. But im having trouble figuring out why its giving me these 2 errors.
error C2664: 'ObjectFactory<T_BaseClass>::RegisterObject' : cannot convert parameter 2 from 'FactoryObject<T> *' to 'FactoryObject<T> *'

error C2440: 'initializing' : cannot convert from 'BaseClass *' to 'ChildClass *'

I believe through class inheritance that ChildClass, should be able to be instanced in BaseClass (as ChildClass inherits BaseClass). (Correct me if im wrong though) Here is my source for the factory. ObjectFactory.h
#ifndef H_OBJECTFACTORY_H
#define H_OBJECTFACTORY_H

#include "FactoryObject.h"

template<class T_BaseClass> class ObjectFactory {
	public:

		//==============================================================

		/**
		* Constructor
		*/
		ObjectFactory() { };

		//==============================================================

		/**
		* Destructor
		*/
		~ObjectFactory() { };

		//==============================================================

		/**
		* Registers a new object type to the factory
		*/
		void RegisterObject(std::string _Key, FactoryObject<T_BaseClass>* _FactoryObject) {

			map<std::string, FactoryObject<T_BaseClass>*>::iterator i = FactoryObjects.find(_Key);
			if(i != FactoryObjects.end())
				FactoryObjects[_Key] = _FactoryObject;

		};

		//==============================================================

		/**
		* Creates a new object from the factory
		*/
		T_BaseClass* CreateObject(std::string _Key) {
			
			map<std::string, FactoryObject<T_BaseClass>*>::iterator i = FactoryObjects.find(_Key);
			if(i != FactoryObjects.end())
				return i->second->newObject();
			else
				return new T_BaseClass(); // We know the base object exists, return it as a default.

		};
		
	protected:

	private:

		// Holds all of our possible Object creations.
		map<std::string, FactoryObject<T_BaseClass>*>			FactoryObjects;


};

#endif

FactoryObject.h
#ifndef H_FACTORYOBJECT_H
#define H_FACTORYOBJECT_H

template<class T> class FactoryObject {
	public:

		//======================================================

		/**
		* Constructor
		*/
		FactoryObject() { };

		//======================================================

		/**
		* Destructor
		*/
		~FactoryObject() { };

		//======================================================

		/**
		* Instances a new class of the class T.
		*/
		T* newObject() {
			return new T();
		}

		//======================================================
	protected:

	private:

};

#endif

This is how im calling the bugger.
	ObjectFactory<BaseClass> GameObjects;
	GameObjects.RegisterObject("ChildClass",new FactoryObject<ChildClass>);

	ChildClass* _ChildClass = GameObjects.CreateObject("ChildClass");

Thanks, GanonPhantom

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by GanonPhantom
I believe through class inheritance that ChildClass, should be able to be instanced in BaseClass (as ChildClass inherits BaseClass). (Correct me if im wrong though)


No. Foo<Base> has no automatic inheritance relationship to Foo<Derived>.

This is for good reason: it would be very dangerous. Consider for example that standard library containers are built on the same kind of templating, and consider that if a std::vector<Derived> were considered to be a kind of std::vector<Base> automatically, then the language would have to allow you to put a Base into a std::vector<Derived> (because "it's a std::vector<Base>", and you can put Bases into one of those). Then consider the implications of that: how do you put a Base into a slot of an array-allocation that was designed to hold Derived instances? How are you supposed to magically get a Base object back (as you should, since that's what you put in) when you ask the vector for that element (and it says "I'm a vector of Derived, so I return Derived objects from my operator[])?

Basically, mixing templating and inheritance - runtime and compile-time polymorphism - is very tricky business. You won't find a solution that easily.

Also, the fact that you have classes named "FactoryObject" and "ObjectFactory" makes things very confusing.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Quote:
Original post by GanonPhantom
I believe through class inheritance that ChildClass, should be able to be instanced in BaseClass (as ChildClass inherits BaseClass). (Correct me if im wrong though)



This is for good reason: it would be very dangerous. Consider for example that standard library containers are built on the same kind of templating, and consider that if a std::vector<Derived> were considered to be a kind of std::vector<Base> automatically, then the language would have to allow you to put a Base into a std::vector<Derived> (because "it's a std::vector<Base>", and you can put Bases into one of those). Then consider the implications of that: how do you put a Base into a slot of an array-allocation that was designed to hold Derived instances? How are you supposed to magically get a Base object back (as you should, since that's what you put in) when you ask the vector for that element (and it says "I'm a vector of Derived, so I return Derived objects from my operator[])?


Ok, i see what you mean there. I think the way ive been looking at it is, im looking at the templates typename as the type, but the not template as the whole type itself (that may not make to much sense when you read it :P )

I thought of making a Base class for the template itself, but then i ran into the problem of not being able to properly call newObject(), but the Base class dosnt have a clue what the return type would be.

Share this post


Link to post
Share on other sites
Aight, this is fixed now. I came up with a semi-hackish solution, but i wont lose to much sleep over it. Here is the source for anyone in the future that is interested in dynamic object factories, or that use the search function :thumbsup:


#ifndef H_OBJECTFACTORY_H
#define H_OBJECTFACTORY_H


//===========================================================================

template<typename T_BaseClass, typename T_ClassType> // semi-hackish solution :-/
T_BaseClass* CreateFactoryObject() {
return new T_ClassType();
}

//===========================================================================

template<class T_BaseClass> class ObjectFactory {
public:

//==============================================================

/**
* Constructor
*/

ObjectFactory() { };

//==============================================================

/**
* Destructor
*/

~ObjectFactory() { };

//==============================================================

/**
* Registers a new object type to the factory
*/

template<typename T_ClassType>
void RegisterObject(std::string _Key) {

map<std::string, ptrCreateFactoryObject>::iterator i = FactoryObjects.find(_Key);
if(i == FactoryObjects.end())
FactoryObjects[_Key] = &CreateFactoryObject<T_BaseClass, T_ClassType>;

};

//==============================================================

/**
* Creates a new object from the factory
*/

T_BaseClass* CreateObject(std::string _Key) {

map<std::string, ptrCreateFactoryObject>::iterator i = FactoryObjects.find(_Key);
if(i != FactoryObjects.end())
return i->second();
else {
return new T_BaseClass(); // We know the base object exists, return it as a default.
}

};

protected:

private:

typedef T_BaseClass *(*ptrCreateFactoryObject)();

// Holds all of our possible Object creations.
map<std::string, ptrCreateFactoryObject> FactoryObjects;


};

#endif



Thanks for the help Zahlman, and if anyone has something they would like to point out in this, weather it be a potential problem, or an improvement that can be made to make it less hackish, please feel free reply. :)

GanonPhantom

Share this post


Link to post
Share on other sites
Hey that is not a hack :)
I went a step further and have a type which is the id, because who wants to be limited to strings.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!