Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prohibit public inheritance but allow private (and protected) inheritance

C++11 introduced the keyword final to forbid future overrides or to prohibit inheritance. The most common example where one may use it is for the case of classes that are not intended to be used as base classes (have e.g. non-virtual destructors). However, sometime we may want to have an is-implemented-in-terms-of relation between two classes (i.e. private inheritance), and not a is-a relationship (public inheritance). However, final prohibits both types of inheritance.

My question is the following: is there any way of allowing private inheritance but forbidding public inheritance (probably not directly, but at least can we "simulate" it)? In this case, there won't be any issues even if we use a class with a non-virtual destructor, as we cannot use directly the derived class via a pointer to base, so we should be fine.

I am thinking of a code like this:

class Base /*final*/ {}; // making it final prohibits both private and public inheritance

class PrivateDerived: private Base{}; // this should work

class PublicDerived: public Base{}; // this shouldn't

int main()
{
    PrivateDerived prvd;
    PublicDerived  pubd; // this should not compile

    // Base* pBase = new PrivateDerived; // doesn't work, so we are ok
}
like image 680
vsoftco Avatar asked May 04 '15 19:05

vsoftco


People also ask

What happens in inheritance in case of public private or protected base class?

public inheritance makes public members of the base class public in the derived class, and the protected members of the base class remain protected in the derived class. protected inheritance makes the public and protected members of the base class protected in the derived class.

How do you make a private accessible inheritance?

You need to define it as protected . Protected members are inherited to child classes but are not accessible from the outside world. after inheriting protected members, you can provide public access. then we should avoid to keep personal data in protected access specifier.

Can protected members be inherited?

The protected members are inherited by the child classes and can access them as its own members. But we can't access these members using the reference of the parent class. We can access protected members only by using child class reference.

How is private inheritance different from public inheritance?

Instead, private inheritance refers to the idea of being "implemented in terms of a". The key difference is that whereas public inheritance provides a common interface between two classes, private inheritance does not--rather, it makes all of the public functions of the parent class private in the child class.


1 Answers

Interesting question! If you don't mind giving up the destructor's triviality, I think the following does the job:

#include <type_traits>

template <typename T>
class Base {
protected:
    ~Base() {
        static_assert(!std::is_convertible<T*,Base*>::value, "Invalid use of public inheritance.");
    }    
};

class Derived : public Base<Derived> {
};

int main() {
    Derived d;
}

The code above fails to compile: the static_assert fires because Derived* is convertible to Base<Derived>*. However if you change the inheritance to either protected or private then the code compiles.

Unfortunately users can still shoot themselves in the foot:

class Bad : public Base<Derived> {
};
like image 84
Cassio Neri Avatar answered Oct 22 '22 23:10

Cassio Neri