Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define 'final' member functions for a class

Tags:

c++

Is it possible to make my member functions final as in Java, so that the derived classes can not override them?

like image 224
Hemant Avatar asked Sep 02 '10 08:09

Hemant


2 Answers

C++11 adds a final contextual keyword to support this:

class B
{
  public:
    virtual void foo() final;
};
class D : B
{
  public:
    virtual void foo(); // error: declaration of 'foo' overrides a 'final' function
};

final is supported in GCC 4.7 and Clang 3.0. And as Sergius notes in his answer, MSVC++ supports it (with the spelling sealed), since MSVC++2005. So if you encapsulate in a mini-macro and set it depending on your compiler, you can be on your way with this. Just make sure you actually are using such a compiler at least every so often, so you'll detect any mistakes early.

like image 140
Jeff Walden Avatar answered Sep 19 '22 20:09

Jeff Walden


It is so much possible that it is in fact the default behaviour. I.e. if you don't declare your class instance methods explicitly as virtual, they can't be overridden in subclasses (only hidden, which is a different - and almost always erroneous - case).

Effective C++ Third Edition, Item 36 deals with this in detail. Consider

class B {
public:
  virtual void vf();
  void mf();
  virtual void mf(int);
  ...
};

class D: public B {
public:
  virtual void vf();              // overrides B::vf
  void mf();                      // hides B::mf; see Item33
  ...
};

D x;                              // x is an object of type D
B *pB = &x;                       // get pointer to x
D *pD = &x;                       // get pointer to x

pD->vf();                         // calls D::mf, as expected
pB->vf();                         // calls D::mf, as expected
pD->mf();                         // calls D::mf, as expected
pB->mf();                         // calls B::mf - surprise!
pD->mf(1);                        // error -  D::mf() hides B::mf(int)!
pB->mf(1);                        // calls B::mf(int)

So this is not exactly how final behaves in Java, but you can only get this close with C++. An alternative might be to prevent subclassing altogether. The technical - working, but not nice - solution to this is to declare all your constructors private (and provide a static factory method if you want to allow instantiation of your class, of course).

like image 26
Péter Török Avatar answered Sep 21 '22 20:09

Péter Török