Jump to content

  • Log In with Google      Sign In   
  • Create Account

Prevent a base class method from being overridden?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 Plethora   Members   -  Reputation: 679

Like
0Likes
Like

Posted 07 March 2013 - 11:30 AM

Pretty straightforward question.  Say I have a base class and a derived class.  Is it possible to create a function in the base class and explicitly prevent the derived class from overriding it?  I know I can do the opposite (force the derived class to override) with a pure virtual function, but have never heard of a way to do this.

 

It's not purely necessary, seeing as I can just *not* override it, but I prefer to make things explicit where possible.  

 

For context:  Basically I have a Main_Controller class whose job it is primarily to do event handling.  This is all fine and good, but I find in my game I have two fairly distinct user interfaces when it comes to hotkeys.  One is related to the world map, towns, explorable areas, etc.  The other is specific to battles and the battleMap.  So rather than having two distinct event handlers in one class I thought it would be a lot more flexible to create a base Controller class, and then derive Main_Controller and a Battle_Controller from it.  When a battle began I would then pass off control to the Battle_Controller class.

 

However, there are some gui events (game options menu type stuff) I would like to ensure are being handled the same way in each.  It seems the most obvious way is to ensure that both derived classes are using the base class function for handling these particular events.


I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!

 

http://infinityelephant.wordpress.com


Sponsor:

#2 King Mir   Members   -  Reputation: 2000

Like
0Likes
Like

Posted 07 March 2013 - 11:46 AM

Just make the method non-virtual. That doesn't prevent the base class from overriding it entirely, but all references to the base class will call the base class's method.

#3 Yourself   Crossbones+   -  Reputation: 1133

Like
5Likes
Like

Posted 07 March 2013 - 12:05 PM

You can use the final specifier (c++ 11)



#4 Plethora   Members   -  Reputation: 679

Like
0Likes
Like

Posted 07 March 2013 - 12:11 PM

final is exactly what I was looking for, thanks!

 

:)


I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!

 

http://infinityelephant.wordpress.com


#5 Servant of the Lord   Crossbones+   -  Reputation: 19556

Like
0Likes
Like

Posted 07 March 2013 - 01:24 PM

Does final work on non-virtual functions?
It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#6 Mussi   Crossbones+   -  Reputation: 1969

Like
2Likes
Like

Posted 07 March 2013 - 02:26 PM

Does final work on non-virtual functions?

No, it can only be used on virtual functions. Same goes for override, as in you can only override a parent class' virtual function.

 

Edit:

The final identifier is there to prevent overriding methods. Technically, I think, you would not be overriding a method if it's not virtual.


Edited by Mussi, 07 March 2013 - 02:33 PM.


#7 Servant of the Lord   Crossbones+   -  Reputation: 19556

Like
0Likes
Like

Posted 07 March 2013 - 02:49 PM

That's what I thought, but I wasn't sure. So 'final' wouldn't actually work in the OP's situation, unless the OP wants a virtual function in the base class that can't be overridden / overloaded - which seems to defeat the purpose of it being virtual (seeing that his described inheritance is only one level deep).

 

I must not be understanding the question. laugh.png


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#8 Plethora   Members   -  Reputation: 679

Like
0Likes
Like

Posted 07 March 2013 - 04:50 PM

That's what I thought, but I wasn't sure. So 'final' wouldn't actually work in the OP's situation, unless the OP wants a virtual function in the base class that can't be overridden / overloaded - which seems to defeat the purpose of it being virtual (seeing that his described inheritance is only one level deep).

 

I must not be understanding the question. laugh.png

 

Perhaps you can tell me if this is what I want.  :)  I'm not exactly advanced when it comes to certain topics in c++, polymorphism being one of them.  I've just never used it a whole lot and thus its very possible I'm messing up my terminology or something like that.  Here's some quick pseudo-code:

 

 

class Controller

{

     virtual void handleEvents(...) = 0;    //<--------derived classes must handle events but can do so however they wish

     void passOffEventToGui(...);           //<--------gui events must be sent off to the gui handler, want to make sure this exact function is called by all derived classes

};

 

that's not quite how my actual program works but it gets the point across.  So I know how the pure virtual function works for handleEvents(...), but I want to ensure that passOffEventToGui(...) works exactly the same way in all derived classes.  Am I even looking at this in the right way?


I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!

 

http://infinityelephant.wordpress.com


#9 Dan Mayor   Crossbones+   -  Reputation: 1712

Like
2Likes
Like

Posted 07 March 2013 - 05:37 PM

Seems like this thread has gotten overly complicated.  Simple answer, a virtual method is overridable until a derivative creates a final version of said method.  A non virtual method is permanent and you just need to ensure that you expose it correctly with the public access qualifier or that your derivative inherits the protected methods (if said method is protected that is).  In other words your pseudo code is correct as is, the virtual handleEvents will be overrideable the passOffEventToGui will not.  That is the purpose of inheritance, that you can "inherit" the methods of one base class into it's derivatives.  The "virtual" is the special keyword or qualifier if you will that makes a method overrideable.


Digivance Game Studios Founder:

Dan Mayor - Dan@Digivance.com
 www.Digivance.com


#10 Servant of the Lord   Crossbones+   -  Reputation: 19556

Like
4Likes
Like

Posted 07 March 2013 - 06:20 PM

If you are using polymorphism, that is, treating a DerivedClass as a BaseClass using either a reference or a pointer, then regular functions can be overloaded but not virtually overridden.
 
#include <iostream>
 
class BaseClass
{
     public:
     void myFunc()  //Can't be overridden, can be overloaded and hidden.
     {
         std::cout << "BaseClass::myFunc() called" << std::endl;
     }
     
     virtual void myVirtualFunc() //Can be overridden, but doesn't have to be.
     {
         std::cout << "BaseClass::myVirtualFunc() called" << std::endl;
     }
     
     virtual void myPureVirtualFunc() = 0; //Must be overridden.
};
 
class DerivedClass : public BaseClass
{
     public:
     void myFunc() //This is an overload, not an override (because Base's myFunc() is not virtual). Polymorphism will not call this function.
     {
         std::cout << "DerivedClass::myFunc() called" << std::endl;
     }
     
     virtual void myVirtualFunc()
     {
         std::cout << "DerivedClass::myVirtualFunc() called" << std::endl;
     }
     
     virtual void myPureVirtualFunc()
     {
         std::cout << "DerivedClass::myPureVirtualFunc() called" << std::endl;
     }
};
 
int main()
{
    //BaseClass baseClass; //Can't be constructed because of pure-virtual.
    DerivedClass derivedClass;
   
    BaseClass &derivedPretendingToBeBase = derivedClass;
 
    derivedClass.myFunc(); //Calls DerivedClass::myFunc().
    derivedClass.myVirtualFunc(); //Calls DerivedClass::myVirtualFunc().
    derivedClass.myPureVirtualFunc(); //Calls DerivedClass::myPureVirtualFunc().
   
    derivedPretendingToBeBase.myFunc(); //Calls BaseClass::myFunc(), because it's not virtual.
    derivedPretendingToBeBase.myVirtualFunc(); //Calls DerivedClass::myVirtualFunc(), because it IS virtual and overridden.
    derivedPretendingToBeBase.myPureVirtualFunc(); //Calls DerivedClass::myPureVirtualFunc(), because it is virtual and overridden.
   
    return 0;
}
See the code results here.
 
If you are using polymorphism, and treating all your derived classes as base classes, the Base function will always be called as long as it's not virtual.
If you aren't using polymorphism, and are using a derived class directly, the derived's functions will always be called, unless it doesn't have that function, then it'll look at any inherited classes and check if they have that function.
 
If you want to enforce that a base class' functions are never overridden don't make it virtual - but it could still be overloaded, and be hidden by any derived classes. But this is never a problem when treating your derived classes as Base pointers or references.
 
All 'final' does is make sure that a virtual function is no longer overridden, in a chain like this:
 
class Base
{
     virtual void myFuncA() { }
     virtual void myFuncB() { }
}

class DerivedA : public Base
{
     virtual void myFuncA() { }
     virtual void myFuncB() final { }
}

class DerivedB : public DerivedA
{
     virtual void myFuncA() { }
     virtual void myFuncB() { } //Compile error! This virtual function was declared 'final' earlier up the inheritance tree. It can't be overridden further.
}

So, given:
DerivedB inherits DerivedA inherits Base
Base *poly = &derivedB;


virtual functions: Starting at the 'real' class (DerivedB), works up until an implementation is found. (Checks DerivedB, then DerivedA, then Base)
Non-virtual functions: Starting at the reference/pointer class (Base), looks in that class, and up the inheritance tree at any classes it inherits from, but does not look down the inheritance tree to any classes that derive from it.

If you are using a class directly (treating a DerivedClass as a DerivedClass, and not as a Base pointer), then you can't stop a user from overriding a function unless you declare it virtual AND final in the BaseClass... which is kinda counter-intuitive and questionable. Virtual implies it can be overridden, final says that it can't be overridden (from this point onward), so a BaseClass that does them both is like saying Yes and No at the same time. It'd work, but why would it be needed?

If Derived wants to override it, it won't harm anything... unless you're using polymorphism. If you are using polymorphism, making it non-virtual solves the problem.
It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#11 Plethora   Members   -  Reputation: 679

Like
0Likes
Like

Posted 07 March 2013 - 06:48 PM

Thanks for both the direct answer to my question and the explanation of the concepts.  Both are very helpful.

 

:)


I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!

 

http://infinityelephant.wordpress.com





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS