Prevent a base class method from being overridden?

Started by
9 comments, last by Plethora 11 years, 1 month ago

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

Advertisement
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.

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

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

Does final work on non-virtual functions?

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.

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

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

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.

Dan Mayor

Professional Programmer & Hobbyist Game Developer

Seeking team for indie development opportunities, see my classifieds post

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.

This topic is closed to new replies.

Advertisement