Polymorphism

Started by
5 comments, last by Zahlman 18 years, 7 months ago
Hello again, I'm having a hell of a time figuring out what I should do with this. What I want to do is: Take my base class as a pointer and set it to some derived class like. SQUARE *grass; grass = new GRASS; . However, when I try this, the only member functions accessible are ones I overloaded in the derived class anything above and beyond them in the derived class I can't access. I want to have different classes of map tiles to be all put in a vector, so I thought this would be the way to do this with out making just one huge class(which kind of defeats the purposes classes I think). The vector that's supposed to be holding these title class's are in the GRID class. Thanks for reading.

int main()
{
	using std::cout;
	using std::endl;

	ITEM item;
	item.m_ItemActive();
	PLAYER player;
	player.m_PlayerActive();

	int x=5, y=5;
	
	GRID grid(x,y);
	SQUARE *gridsquare;
	gridsquare = new GRIDSQUARE;
	gridsquare->m_Init(3,3);
	gridsquare = grid.findSquare(2,4);
	gridsquare->m_addItem(item);
	gridsquare->m_addItem(item);
	gridsquare->m_addPlayer(player);
	grid.m_showSquares();

        delete gridsquare;

	return 0;
}


Advertisement
Hmm, the code does not look that bad. At first I thought you were talking about C++, but it looks to me that your code is either C# or VB. It would be nice if you could specify next time. On the other hand, Having a large class like in your circumstance might well defeat the purpose you were talking about. Back to the drawing board lol.
Through a SQUARE*, the only member functions you can use are those which are declared in SQUARE, for the simple reason that the compiler cannot know, at compile time, whether a given SQUARE* is really pointing to a SQUARE object, to a GRASS object or to something else.

While the dynamic type of the object may vary (depending on what you create with new), the static type of the object is defined by the type of the pointer variable.

There are ways to do a safe dynamic cast, converting the SQUARE* to a GRASS* and thus getting access to the member functions in GRASS, but it is generally better to rely on overriding virtual functions declared in the base class (SQUARE).

The syntax for such a dynamic cast is ... GRASS* grass = dynamic_cast<GRASS*>(square);. This will only work correctly it SQUARE (and thus GRASS) is a polymorphic type, i.e. a type which has a virtual member function. If square wasn't really pointing to a GRASS object, then dynamic_cast will return 0 - a NULL pointer. Otherwise it will return a pointer to the correct type.

Do not abuse this, as it has significant run-time performance consequences. You are much better off either relying on the common interface or separating your different classes into different containers.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Thanks for your replies,
Yeah I was trying to avoid dynamic cast, and the whole huge base class thing. Guess I get to modify my containers: D. Thanks again.

Sorry about not specifying the language.
Some things in your code look wrong.

The obvious but not too important one is gridsquare = new GRIDSQUARE; Now I know that this compiles and works, but that doesn't mean that you should do it. You should do this: gridsquare = new GRIDSQUARE();

These three lines here look like a memory leak to me:

gridsquare = new GRIDSQUARE; /* ok gridsquare points to object A, since only gridsquare knows about A, gridsquare "owns" A and thus is responsible for deleting it unless it can hand off ownership of A */

gridsquare->m_Init(3,3); /* object A is initialized (could have been done in constructor but no big deal */

gridsquare = grid.findSquare(2,4); /* object B is assigned to gridsquare. What happened to A? It will never get deleted because its owner lost track of it. */


Oh and how to get access the more specific functions of your objects? You can have a vector full of pointers to all of your squares, and then have another vector full of pointers to just your grass squares. Each vector would have a pointer to each grass square. Thus if you wanted to loop through all of the grass squares to call a grass specific function you would loop through the vector of grass squares, whereas if you wanted to call a function on every square you would look through the vector with all of the squares.
I was aware of that memory leak :D. I only put that in there to make it painfully clear what I was trying to do. Which was to make a SQUARE of the type GRIDSQAURE with out that little memory leak there that would have been hard to see I think. Good eye though.

As for me not using the constructor for Init. The Constructor can not return a value which isn't very good for error checking as far as I know. I want to make sure my program does not continue if Init() fails. I know it doesn't look like I'm doing that with the code, but that's the intent once the program matures a little bit.

Correct me if I'm wrong.
Consider: what can a GRASS square *do* that an ordinary SQUARE cannot? Won't you be ok with just virtual functions in the SQUARE class?

This topic is closed to new replies.

Advertisement