Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++ forbid private inheritance of a final class?

Tags:

c++

final

C++11 introduced the final keyword to C++.

It can be used on a virtual method or on a class.

Declaring a class final forbids any kind of inheritance: public, protected and private.

struct A final {
};

class B: private A {
};

 error: base 'A' ^ is marked 'final'

While it can be reasonable to forbid public inheritance (e.g. if my class doesn't have a virtual destructor, or for other reasons), why should I forbid private inheritance?

Might it be that if final forbade only public inheritance, that std::string and its other friends in std would have been final -- as they should -- for not having a virtual destructor?

EDIT:

Howard Hinnant already answered Why the standard containers are not final but still, there is a reason for declaring a class final but allowing private inheritance.

like image 214
Amir Kirsh Avatar asked Dec 25 '18 08:12

Amir Kirsh


People also ask

Why do we need private inheritance in C++?

The private inheritance allows access to the protected members of the base class. The private inheritance allows Car to override Engine's virtual functions.

Can private members of a class be inherited?

The private members of a class can be inherited but cannot be accessed directly by its derived classes. They can be accessed using public or protected methods of the base class. The inheritance mode specifies how the protected and public data members are accessible by the derived classes.

Does C have inheritance concept?

No it doesnt. C is not an Object Oriented language. Inheritance is a property of OO languages.

How do you restrict a class from inheritance in C++?

The concept of preventing the inheritance is known as final class. In Java or C#, we can use final classes. In C++ there are no such direct way. Here we will see how to simulate the final class in C++.


2 Answers

Inheritance is inheritance. Accessibility is orthogonal to it. It only protects from statically treating the derived class as the base, outside the scope of the derived class. It makes no difference at runtime, and if private inheritance was allowed, you could write this:

struct C {
    virtual void foo() {}
};

struct A final : C {
    virtual void foo() {}
};

void baz(A& ref) { ref.foo(); }

class B: private A {
   virtual void foo() {}
   void bar() {
       baz(*this);
   }
};

Private inheritance doesn't stop you from using run-time polymorphism. If final is meant to fully prevent further overriding, then private inheritance must be included in the prohibition.

like image 91
StoryTeller - Unslander Monica Avatar answered Oct 11 '22 21:10

StoryTeller - Unslander Monica


In addition to what Story Teller said, consider the reason for introducing final: It's supposed to help optimizations.

When a class is final, and you have a pointer to it, the compiler can prove which member function you are calling, even if it's virtual. If the class is not final, the pointer could actually be a pointer to some derived class, which could conceivably override the virtual method, forcing a full dynamic vtable lookup.

Whether the inheritance is private or not, it is always possible to create a base-class pointer. In the case of private inheritance, the creation of this base-class pointer would be restricted to the deriving class, the derived class, and any base of the derived class, which is still more code than the optimizer has available to make its decisions. As such, only forbidding all inheritance allows the virtual call optimizations to be made.

like image 21
cmaster - reinstate monica Avatar answered Oct 11 '22 21:10

cmaster - reinstate monica