Sign in to follow this  
matthughson

Calling A Parents Virtual Function

Recommended Posts

Hey All, I'm writing a level editor right now for a game I am working on (written in C/C++). The editor runs of the same engine as the actual game, which has lead to a few problems. One such problem is my main update function. My game is attempting to be OOP, and I have a class hiearchy that, at it's simplest form, looks like this: BASE_CLASS - ANIMATED_BASE CLASS - MAIN CHARACTER (ETC.) | \ | PARTICLE_SYSTEM_BASE - MOVING PARTCLE SYSTEM (ETC.) | STATIC_IMAGE_BASE - MENU BUTTON (ETC.) I have a list of Base_Entity's that I iterate through every frame and call a virtual function for updating the entity (the function is in every class). The problem is that when I'm running the level editor I don't want to call the high level class's update function (ie. Main Character), because that does stuff like move the character around, apply gravity to the entity, etc. So what I want to do is call the entity's parents update function (the second level of inheritance, in the case of the Main Character class it would be the Animated Entity's update function). Basically what I want to know is if there is a way to call that second layer of inherited classes functions. Keep in mind I am doing this though a list of Base Entity's. I know I can scope in the function directly, but I'm looking for a single line of code that will work for all inherited classes. I've also thought about just putting in an 'if statement' to see if the level editor is running or not in all the class's update functions, but I'd rather do this with the language's operators. If something doesn't make sense, let me know. Thanks! Matt Hughson

Share this post


Link to post
Share on other sites
If I understand what you're asking, then you just call the function with the qualified name for the class who's virtual function you wish to invoke. e.g.:

struct GrandParent {
virtual void poke(void) {
std::cout << "GrandParent::poke()" << std::endl;
}
};

struct Parent : GrandParent {
virtual void poke(void) {
std::cout << "Parent::poke()" << std::endl;
}
};

struct Child : Parent {
void poke(void) {
std::cout << "Child::poke()" << std::endl;
}
};


int main() {
Parent * child = new Child();

child->poke();
child->Parent::poke();
child->GrandParent::poke();

delete child;

return 0;
}

Share this post


Link to post
Share on other sites
IMHO, the cleanest way (if I get you right) would be to seperate the drawing and physics functionality into two functions. This also enables you to execute them seperately in the game (first process all object's physics, then draw all objects), which might make sense if an object could modify another during its update.

Another possibility (although perhaps less convenient) would be to create an updateGame() and an updateLevelEditor() function inside BASE_CLASS, the first being called when playing the game and the latter being called by the level editor.

Finally, if you want to stick to just one update() function, you might try the following:

BASE_CLASS* bp;
// Initialize bp
bp->BASE_CLASS::update();


I don't know if this will work or not.

Quote:
Original post by matthughson
If something doesn't make sense, let me.

That doesn't make sense. ;)
Nah, just kidding.

EDIT: Oops, you already edited that. Nevermind ;)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I don't think this is possible in c++, but it wouldn't be a good way anyway imho. What I would do is just create a new virtual function which is only inherited up to the second layer, and then you call that function from your base class:


class GrandParent
{
public:
virtual Update(){...}
virtual UpdateSecondLayer(){...}
};

class Parent : public GrandParent
{
public:
virtual Update(){...}
virtual UpdateSecondLayer()
{
Update();
}
};

class Child : public Parent
{
public:
// now don't overload the UpdateSecondLayer function any more
virtual Update(){...}
};


Share this post


Link to post
Share on other sites
Looks like all signs point to if statements... sigh...

Thanks for all the help though guys!

Matt Hughson

PS -
Quote:
That doesn't make sense. ;)
Nah, just kidding.

EDIT: Oops, you already edited that. Nevermind ;)


You just got served.

Share this post


Link to post
Share on other sites
(I was that AP above, I forgot to log in)

What's wrong with my solution? It looks much cleaner than that if statement imho.

EDIT: in my previous post the UpdateSecondLayer function should be:

virtual UpdateSecondLayer()
{
Parent::Update();
}

so that it explicitely calls it's own version.

[Edited by - quasar3d on August 17, 2004 4:39:19 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by quasar3d
(I was that AP above, I forgot to log in)

What's wrong with my solution? It looks much cleaner than that if statement imho.


Hey, sorry. I was typing that before I saw your reply. Your solution seems like a good one, it just means a lot of re-typing. I was really just hoping to find out there was an operator that called an object's parent's version of a virtual function.

Thanks again for the help!
Matt Hughson

Share this post


Link to post
Share on other sites
I need to reread the exact details to check exactly what you want, but here's some general info for OO design.

The basic rule is this, there are 2 clients to a virtual function, derived classes and object users ...

users of objects should absolutely never explitly call a certain function if the function is virtual, that means your design has some flawed assumption in it if you ever want to do such a thing.

derived classes should ONLY ever need to call their own virtual functions (which is the default) and their direct parent's virtual functions (which in turn can chain the message up the tree as needed) ... there is no case where a class should ever call it's grandparents version of a virtual function directly.

Share this post


Link to post
Share on other sites
Quote:
Original post by Xai
I need to reread the exact details to check exactly what you want, but here's some general info for OO design.

The basic rule is this, there are 2 clients to a virtual function, derived classes and object users ...

users of objects should absolutely never explitly call a certain function if the function is virtual, that means your design has some flawed assumption in it if you ever want to do such a thing.

derived classes should ONLY ever need to call their own virtual functions (which is the default) and their direct parent's virtual functions (which in turn can chain the message up the tree as needed) ... there is no case where a class should ever call it's grandparents version of a virtual function directly.


Yeah, I hear you. The engine follows what rules I do know regarding OOP, but this level editor is kind of being slammed into the picture so sacrafices must be made.

Matt Hughson

Share this post


Link to post
Share on other sites
Quote:
Original post by matthughson
Yeah, I hear you. The engine follows what rules I do know regarding OOP, but this level editor is kind of being slammed into the picture so sacrafices must be made.

Matt Hughson


If I understand the problem, couldn't you just pass the address of the parent on down to each derived class. So the parent would create a derived class like: new MainCharClass(this);
Then to call the parent just do from the char class,
parent->update();

I'm not sure I even understood what you were asking though, so this might not be what you are looking for.

Share this post


Link to post
Share on other sites
I just force the 'pause' state in my level editor. This causes the delta or dt passed to all the update functions to be 0, doing mostly nothing, even though functions that do physics are called. This function isn't called nearly as often as it is in game, since it would amke the editor very unresponsive. It only calls that function when things are moved, to update the transformation matrices.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnGalt

If I understand the problem, couldn't you just pass the address of the parent on down to each derived class. So the parent would create a derived class like: new MainCharClass(this);
Then to call the parent just do from the char class,
parent->update();

I'm not sure I even understood what you were asking though, so this might not be what you are looking for.


Hmmm... I think you got it. Cash and prizes are en route!

Edit: Cash and prizes may not exist

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