Making a class non-inheritable

How do I make a class non-inheritable in C++? I know that this can be easily achieved in Java using the keyword "final". How can I achieve this in C++ (other than declaring const/dest private or protected?, coz this is just a workaround and not the solution)?
You can't.
I read the above link on the finalclass, wrote the following program and tested it on VS2008 Pro:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
using namespace std;

template<typename T>
class MakeFinal
{
private:
  ~MakeFinal() { };
  friend T;
};

class FinalClass : virtual public MakeFinal<FinalClass> 
{
public: 
	FinalClass() { cout << "FinalClass::ctor" << endl;}
	~FinalClass() { cout << "FinalClass::dtor" << endl;}
};

class NotPossible : public FinalClass
{
public:
	NotPossible() { cout << "NotPossible::ctor" << endl;}
	~NotPossible() { cout << "NotPossible::~ctor" << endl;}
};

int main()
{
	FinalClass fc;
	NotPossible np;// no compiler complaint, why?

	return 0;
}


There is no compiler complaint on line 29. Did I miss something?
Last edited on
because NotPossible is possible.

The child class only calls the dtor of its parent, not its parent's parent.

ie:
1) ~NotPossible [public] calls ~FinalClass [public]
2) ~FinalClass [public] calls ~MakeFinal [private]

Because FinalClass is a friend of MakeFinal, it can access the private dtor. Therefore there's no problem here.
Inspired from this post, I just read about virtual destructors (without the use/knowledge of which so far I have existed).

So a question comes to mind: how are virual functions actually called? Does the object keep "secret pointers" to the virtual functions? How are virtual functions realized on the low level? The basic example being:

1
2
3
4
5
6
7
8
9
10
class Base
{
public:
  virtual  ~Base(){};
}
class Derived: public Base
{
public:  
  ~Derived(){};
}


Now if you call
1
2
Base a= new Derived; 
delete a;

the ~Derived() will be executed with pointer this==&a. So how come? Where is the pointer to ~Derived() stored?
Cheers!
Classes that contain at least 1 virtual function have a hidden group of function pointers for all virtual functions. This group is often known as the "vtable". The vtable is constructed automatically in a class's ctor, and when a virtual function is called, the vtable is determined to know which function to call.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base
{
public:
  virtual ~Base() { }  // because it's virtual, this creates an entry in the vtable for 'dtor'

  Base()
  {
    // 'dtor' is set to point to ~Base() here
  }
};

class Derived : public Base
{
public:
  ~Derived() { }  // because Base::~Base is virtual
      // this is also virtual, even if you don't use the virtual keyword

  Derived()
  {
    // 'dtor' in the vtable is set to point to ~Derived() here
  }
};


Where and how the vtable is stored is up to the compiler to determine, so it's not something you should try to mess with manually in your code.
According to the link mentioned by return 0 in the 3rd reply:
http://www.codeproject.com/KB/cpp/finalclass.aspx

The NotPossible class should NOT be able to inherit from the FinalClass (the compiler should complain), but in my test code, it can (no compiler complaint). What did I miss from what the link says?
Last edited on
Hrm. Maybe the virtual inheritance changes it somehow.

I'm messing with this now. Unfortunately I'm having a problem getting it to compile (just the MakeFinal class, even if I remove the other two it still doesn't like that friend declaration). Will post later


EDIT:

No wonder I couldn't get it to compile. The code is illegal. See the response to the article on that page:

http://www.codeproject.com/KB/cpp/finalclass.aspx?fid=16067&select=763220#xx763220xx

But even his propsed "fix" (really a hack to work around the problem) doesn't work in GCC.

Conclusion: don't use this code.

That said... I went ahead and tried it without the template bits:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MakeFinal
{
private:
    ~MakeFinal() { };

    friend class FinalClass;
};

class FinalClass : virtual public MakeFinal   // <-- virtual is the key
{
public:
	FinalClass() { cout << "FinalClass::ctor" << endl;}
	~FinalClass() { cout << "FinalClass::dtor" << endl;}
};


class NotPossible : public FinalClass
{
public:
	NotPossible() { cout << "NotPossible::ctor" << endl;}
	~NotPossible() { cout << "NotPossible::~ctor" << endl;}
};


And it didn't work on my machine (NotPossible throws an error like you might think). This is, in fact, due to the fact that MakeFinal is inherited virutally. If you remove that keyword then it works. I just didn't notice the virtual keyword in my original post in this thread.

Anyway, it sounds like your compiler is just letting code compile that it shouldn't. What compiler are you using?
Last edited on
@Robertlzw: I experienced the same issue of the code getting compiled, just like you did. I then tried making the constructor private and tried to instantiate "NotPossible np"; and this time around the compiler threw error as expected (could not access private members in the base class).

So apparently, if the constructor is private (regardless of destructor), the FinalClass is "really" the final class, however if the constructor is public (regardless of destructor), you can inherit from the FinalClass.

Don't know the reason yet.

[EDIT]

Below gets compiled:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MakeFinal
{
public:
	MakeFinal() { cout << "Constructor of MakeFinal called" << endl; }
private:
	~MakeFinal() { cout << "Destructor of MakeFinal called" << endl; }
};

class Test : virtual public MakeFinal
{
public:
	Test() { cout << "Test::Const" << endl; }
	~Test() { cout << "Test::Dest" << endl; }
};

int main()
{
    Test t;
}


Below will not get compiled.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MakeFinal
{
private:
	MakeFinal() { cout << "Constructor of MakeFinal called" << endl; }
private:
	~MakeFinal() { cout << "Destructor of MakeFinal called" << endl; }
};

class Test : virtual public MakeFinal
{
public:
	Test() { cout << "Test::Const" << endl; }
	~Test() { cout << "Test::Dest" << endl; }
};

int main()
{
    Test t;
}
Last edited on
The link that Return 0 posted makes some factual errors -- so I wouldn't consider it final [pun intended]. (I think it was written by someone trying to figure things out for himself.)

Virtual Destructors
The purpose of virtual destructors is to handle proper destruction from a base class pointer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;

#define VIRTUAL virtual
//#define VIRTUAL

struct base
  {
  base() { cout << "base ctor\n"; }
  VIRTUAL ~base() { cout << "base dtor\n"; }
  };

struct derived: public base
  {
  derived() { cout << "derived ctor\n"; }
  virtual ~derived() { cout << "derived dtor\n"; }
  };

int main()
  {
  base* p = new derived;

  cout << "\nNow for the fun\n\n";

  delete p;

  cout << "\nBye bye\n\n";
  return 0;
  }

Try the code with VIRTUAL defined as nothing also to see the difference. Unless the base class has a virtual destructor calling the destructor through a base class pointer will fail to call derived class constructors.

You don't need a virtual destructor if you don't plan to destruct from a base class pointer. Replace main() with the following and try again...
1
2
3
4
5
6
7
8
9
int main()
  {
    {
    derived p;
    cout << "\nNow for the fun\n\n";
    }
  cout << "\nBye bye\n\n";
  return 0;
  }
It works both ways...

(Notice that the derived class's destructor does not need to be virtual -- but in general it should be.)


Keywords like Java's final is really a bit of fluff. In C++, to accomplish a non-inheritable class, you should have it listed in big bold letters that you should not inherit from the class.
1
2
3
4
5
6
//
// Hey!  D O N ' T   I N H E R I T  from this class!
//
// Your interocitor will fry.
//
class Quux

Against the usual 'document once' philosophy, I recommend it be indicated
- in the header file
- in the source file
- in the documentation


Personally, however, I don't understand why people have such a thing for making classes un-inheritable. The whole point of classes is to be inheritable. Exactly how often can you really say, "Hey, there is never going to be a need to inherit from this class...".

The purpose of inheritance is upgradability and maintainability. Make a class final and you are back in the dark ages of maintenance.

Hope this helps.

Well, off to get my toe X-Rayed. :-|
Thanks a lot for the good discussion. I use the compiler that comes with Visual C++ 2008 pro. Yes, if FinalClass' ctor is made private, the compiler complains on the line of NotPossible's ctor about "cannot access private member declared in class 'FinalClass' ".

I personally totally agree with you guys: making a class non-inheritable is no good. The code mentioned in the link was just for the sake of having a counterpart in C++ because Java has it. It is against C++ standard. At least I will not use that code.
I think I read somewhere that it was in the works (or at least under discussion) for C++0x... it isn't on the Wiki page though.
Hey, I just stumbled across this again in the C++ FAQ-Lite
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.11
Topic archived. No new replies allowed.