Jump to content
  • Advertisement
Sign in to follow this  
Servant of the Lord

Virtual function question

This topic is 2422 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

I have a class (GameObject) that receives and handles input, which other classes inherit. It has virtual functions for handling the input (called React()).

I have another class (MoveableObject) that inherits the first class, using React(), to provide dragging and double clicking functionality (among other common features). This class is also intended to be inherited.

I want a third class (for example, GuiImage) to inherit MoveableObject, and to overload React(), but when it is cast to a GameObject pointer, and React() is called on it, I want MoveableObject's React() to be called, and then I want MoveableObject to call GuiImage's React().

GameObject
[size=1]SubClassed as...

MoveableObject
[size=1]SubClassed as...


GuiImage

Basically, I want to MoveableObject to intercept GameObject's virtual React() call before it gets to GuiImage.

How can I do that? I would have MoveableObject privately inherit GameObject, but GuiImage needs the majority of GameObject's public functions.

Could I somehow do something like this:
class MoveableObject : public GameObject
{
private:
void GameObject::React(); //Moving just this function into private space.

public:

virtual void React(); //Creating a new identically named function.
};

//Re-implement the inherited function, but specifying scope.
void MoveableObject::GameObject::React()
{
//Code before.

//Call subclass' React() function.
this->React();

//Code after.
}

//Implement the default implementation of the new virtual function.
void MoveableObject::React()
{

}


Is it acceptable to have two identically named member functions (one inherited and one new), and specify the scope for it?

I would rather not have MoveableObject's new React() function be named something differently (like MyReact()), that'd be undesirable - but I can't think of any other way.

Share this post


Link to post
Share on other sites
Advertisement
If you want to call the super class' implementation, you can call it by calling SuperClass::Method()

So let GuiImage::React() call MovableObject::React() the first thing it does, and it should behave as you want if I understand you correctly.

Unless you for some reason _dont_ want this behaviour when React is called on a GuiImage-pointer, but that sounds like a pretty funky requirement.

Share this post


Link to post
Share on other sites

If you want to call the super class' implementation, you can call it by calling SuperClass::Method()
So let GuiImage::React() call MovableObject::React() the first thing it does, and it should behave as you want if I understand you correctly.

Yeah, that's the functionality I want, though it'd be nice if it happens automatically without having to specifically call MoveableObject::React(), and that's what my poorly worded question was asking. tongue.png

Basically, if GuiImage would normally inherit from GameObject perfectly fine, I'd like that if I made it inherit MoveableObject instead (which in turn inherits GameObject), that MoveableObject would intercept some of GameObject's virtual function calls before passing them on to GuiImage, without GuiImage having to manually call MoveableObject::React().

Share this post


Link to post
Share on other sites
First, though your code is OK on syntax, I would avoid that at all cost.
Two identical names distinguished by scope is not a good idea to me.
What does other developer think when reading your code?
Can he understand it without detailed document? No.

For your question, just introduce another virtual function.


class MoveableObject : public SomeSuper
{
public:
virtual void React(); // override super, and call this->doReact()

protected:
virtual void doReact(); // to be overrided by derived.
};
class GuiImage : public MoveableObject
{
protected:
virtual void doReact(); // do my action here.
};


Also, I prefer NVI idea -- Non virtual interface to virtual interface, but that's another topic.

Share this post


Link to post
Share on other sites

First, though your code is OK on syntax, I would avoid that at all cost.

So that is actually allowed in standardized C++?
Two identical names distinguished by scope is not a good idea to me.[/quote]
I'd tend to agree, but I feel in this case it's not a problem since only to that one class both functions are visible. To the superclass and to subclasses, only one function is visible, so it's relegated to implementation detail and not an interface detail.
What does other developer think when reading your code?
Can he understand it without detailed document? No.[/quote]
I think so, it's basically just a 'decorator pattern' but for virtual function calls. The point is that one function call would replace the other function call, still only exposing one React() function publicly to subclasses. The superclass (GameObject) doesn't need to know that the subclass (MoveableObject) swaps around virtual functions, nor does subclasses (like GuiImage) need to know.
It's a very weird quirk, I'd admit; I'd love to avoid it, but I can't think of a cleaner way to do it without re-structuring alot of logic. The only reason why I'm even considering it is because it's entirely self-contained and blackboxed in a single class with no public or protected exposure.
I'll put more thought into it to see if there is a better way. I'd rather not rename the React() function because other classes inherit from the superclass (GameObject) without going through Moveable object, and I want to keep them consistent not having to remember to use doReact() for objects that inherit MoveableObject, and just React() for objects that inherit GameObject (of which there will be plenty of classes in both categories).

Share this post


Link to post
Share on other sites

So that is actually allowed in standardized C++?

Hmmm.
I thought you gave compilable code but now seems you didn't.
I tried your code in both VC and GCC, both failed compile on that void GameObject::React();


The superclass (GameObject) doesn't need to know that the subclass (MoveableObject) swaps around virtual functions.

When a super class has a virtual function, it really knows the subclass will change the default behavior of the virtual function.
So that sounds not a problem.


I'll put more thought into it to see if there is a better way. I'd rather not rename the React() function because other classes inherit from the superclass (GameObject) without going through Moveable object, and I want to keep them consistent not having to remember to use doReact() for objects that inherit MoveableObject, and just React() for objects that inherit GameObject (of which there will be plenty of classes in both categories).

Seems doReact is too general in your case. Maybe you can name it as doReactForMovableObject so that it belongs to MovableObject only.

Share this post


Link to post
Share on other sites

Also, I prefer NVI idea -- Non virtual interface to virtual interface, but that's another topic.


You made your interface virtual though. React should be non-virtual.

Share this post


Link to post
Share on other sites
In java, you have the super keyword to do what you want.
Unfortunately you don't in C++.

But what is the reason really you want to do this? How often are you changing base class?
Is saving 2seconds of work when you change base class, really worth all this effort, and obfuscated code?

Share this post


Link to post
Share on other sites

In java, you have the super keyword to do what you want.
Unfortunately you don't in C++.


You can do it in C++ "manually".


class A
{
protected:
virtual void tellMe();
};

class B : public A
{
private:
typedef A super;
protected:
void tellOther() {
super::tellMe(); // call A's tellMe
}

virtual void tellMe();
};


Then if you change the base A to other class, you only need to change that typedef.
Note the private scope of super, it's important so that derived classes will not wrongly use base's super.

Share this post


Link to post
Share on other sites
I heeding the advice given, and just renamed React(), but I took it a another step and made MoveableObject a stand-alone class that doesn't inherit from GameObject, and is instead passed a copy of GuiImage in the constructor.

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!