Base class constructor interface

Started by
3 comments, last by Bregma 17 years, 4 months ago
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]
Advertisement
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.
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.
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]
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.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement