Sign in to follow this  
Kest

Base class constructor interface

Recommended Posts

This would probably be easier shown than explained, so here goes..
class MapObj
{
public:
	static MapObj& Create(Generator &g);	// Create with generator
	static MapObj& Create(File &f);		// Create with file
	static void Destroy(MapObj &inst);	// Destroy the object
private:
	int Type;
	Data members...
};

class Item : public MapObj
{
public:
	Interface...
protected:
	Item() {}
	virtual ~Item() {}
	void Make(Generator &g);
	void Make(File &f);
private:
	Data members...
};

class Char : public MapObj {...};
class Suit : public MapObj {...};

MapObj& MapObj::Create(Generator &g) // *static*
{
	MapObj *inst = null;
	switch( g.GetType() )
	{
		case MAPOBJTYPE_ITEM:
		{
			Item *i = new Item;
			i->Make( g );
			inst = i;
		} break;

		case MAPOBJTYPE_CHAR:
		{
			Char *i = new Char;
			i->Make( g );
			inst = i;
		} break;

		case MAPOBJTYPE_SUIT:
		{
			// Some objects have more complications
			Kit *k = new Kit;
			k->Make( g );
			Suit *i = new Suit;
			i->Make( k );
			inst = i;
		} break;

		case ....
	}

	inst->DataMemberX = g.GetX();
	inst->DataMemberY = g.GetY();
	...

	return *inst;
}

MapObj& MapObj::Create(File &f) // *static*
{
	MapObj *inst = null;
	int type;
	f.Load( type );
	switch( type )
	{
		case MAPOBJTYPE_ITEM:
		{
			Item *i = new Item;
			i->Make( f );
			inst = i;
		} break;

		case ...
	}

	f.Load( inst->DataMemberX );
	f.Load( inst->DataMemberY );
	...

	return *inst;
}
I want to hide the complexity of creating the objects in this one bit of code. So I figured that by making the constructors and Make() functions protected, only the base class could mess with them. But (as I've just recently discovered) I can't call the protected constructors, destructors, or the Make() functions of the derived objects from the static base class functions. I had always thought that base classes could call protected functions of derived objects. But I guess it only goes one way. Obviously, I'm going about this the wrong way. So I'm looking for someone to point towards another direction. Please let me know if I've left any important information out. And thanks in advance for any ideas. [smile]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
One solution:

create MapObjFactory class (some prefer MapObjManager)
MapObjFactory is singleton and has function to create new MapObj instance
MapObj objects hides its constructors to pretty much everyone except this Factory class vias friend declaration


Second solution:

For each terminal class inherited from MapObj create static method Create which can create instance of its class.

Share this post


Link to post
Share on other sites
0) Reconsider why they are 'protected'. The answer may guide you to a different solution.

1) You can make the Create functions be 'friend's and that should do it, I think.

2) But why do you have a virtual Make() anyway? Are constructors somehow insufficient?

3) Returning a reference to dynamically allocated memory is IMHO very sketchy. It hides the pointer-ownership responsibility, and leaves the caller writing things like 'delete &obj;' which looks really ugly. Instead, consider returning a std::auto_ptr<MapObj>. You can still get polymorphic behaviour through the auto_ptr.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
create MapObjFactory class (some prefer MapObjManager)
MapObjFactory is singleton and has function to create new MapObj instance
MapObj objects hides its constructors to pretty much everyone except this Factory class vias friend declaration

If I create a new singleton class to generate the derived types, wouldn't I be in the same boat I'm in now? The management of these other types only consists of three static functions, so it's not really a big mess that I want to organize. I just want to make it work.

Quote:
For each terminal class inherited from MapObj create static method Create which can create instance of its class.

This was my original design. But the derived objects had to constantly call base class versions of the creation functions. I hate having to do that. It would be great if I could leave all of that complication out of the derived objects, and keep their creation process as simple as possible.

Quote:
Original post by Zahlman
0) Reconsider why they are 'protected'. The answer may guide you to a different solution.

I listed them as protected to limit access to only the base class. But that was a misguided strategy. Is there something else I'm missing?

Quote:
1) You can make the Create functions be 'friend's and that should do it, I think.

I thought about that. But I've never used friend functions, and the first thing I read when I looked them up was that they break object oriented design. I'm not sure if allocating/creating derived objects from a base class is considered breaking OO design, but I figured I would quickly find out here :)

Quote:
2) But why do you have a virtual Make() anyway? Are constructors somehow insufficient?

The make functions are not virtual. The base class has no Make() functions. Perhaps that's why the whole protected problem popped up on me. If they were virtual, it probably would have worked.. well, except for the constructors.

Quote:
3) Returning a reference to dynamically allocated memory is IMHO very sketchy. It hides the pointer-ownership responsibility, and leaves the caller writing things like 'delete &obj;' which looks really ugly.

I check the allocation in the functions where they are called. But hiding the responsibility is exactly what I want to do. Calling code would never call delete &obj. They would call MapObj::Destroy( obj ). Well, assuming any of this was actually working.

I appreciate your time and advice [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
Quote:
1) You can make the Create functions be 'friend's and that should do it, I think.

I thought about that. But I've never used friend functions, and the first thing I read when I looked them up was that they break object oriented design. I'm not sure if allocating/creating derived objects from a base class is considered breaking OO design, but I figured I would quickly find out here :)


You need to get yourself a better reference.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this