0

I have a problem where I only have to inherit base class once. After that I want to stop anyone from inheriting this class. Can someone explain me how this can be achieved. Moreover if the the number of times base class is inherited is n times (eg 1 ..10) what will be the generic way to do so.

I know that using friend class in base class can solve my problem to some extent. But I find this to be clumsy.Also I have read about Restrict inheritance to desired number of classes at compile-time . I was not able to understand the answer completely.

Can someone suggest me better ways to restrict inheritance at compile time in c++.

  • I find the depth of the inheritance tree to be a major impediment to understanding a class. Good on you for asking how to limit it. – Mark Ransom Jan 07 '19 at 04:48
  • @MarkRansom From what I can tell, OP is asking how to limit the breadth of the inheritance tree, not its depth. – Miles Budnek Jan 07 '19 at 04:53
  • Yes, I want to limit the breadth of inheritance tree. – user2033594 Jan 07 '19 at 04:55
  • 1
    You really need to allow a certain number of unknown derived classes? Or you need to prevent any additional derived classes that aren't in the specific intended implementation? Can you say a bit about why? This sounds like an X-Y Problem; there may be better ways to protect from whatever harm additional derived classes might pose. – aschepler Jan 07 '19 at 04:58
  • currently base class is inherited once by internal team. Now this class is available to a third party. However I don't want them to inherit this base class. So this is the problem statement – user2033594 Jan 07 '19 at 05:02
  • Do you mind callers having access to its *pure virtual interface*? Is it just the functionality/implementation you want to restrict? – Galik Jan 07 '19 at 05:43
  • #Galik No I won't mind callers having access to pure virtual interface – user2033594 Jan 07 '19 at 05:50
  • 2
    *"Moreover it would be fine if it can restrict inheritance at runtime."* What do you mean ? we cannot create class/hierarchy at runtime... – Jarod42 Jan 07 '19 at 08:18
  • 1
    This sounds like a mis-feature. Document what your class does and how it's intended to be used. If someone misuses it that's their problem, not yours. – Pete Becker Jan 07 '19 at 14:04
  • Please provide a clear MCVE (and very brief example of what you currently do and what you want to prevent). As it stands, your questions is rather confusing and unclear, hence liable to closure. – Walter Jan 07 '19 at 22:19
  • @Jarod42 it was from the link that I shared. Anyway I have removed the line. – user2033594 Jan 08 '19 at 03:50

3 Answers3

1

currently base class is inherited once by internal team. Now this class is available to a third party. However I don't want them to inherit this base class. So this is the problem statement

The problem is that C++ does not provide any means for restricting inheritance in such manner directly.

Pointer to implementation idiom might help you get around anyway:

class PublicToUser final
{
    class PrivateToUser;
    std::unique_ptr<PrivateToUser> implementation;
public:
    // ***
};

It now will be the private inner class that actually inherits, but this can be completely hidden away, i. e. you don't need to expose that base class to the user at all – what's not visible will not be inherited...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
0

I have a problem where I only have to inherit base class once. After that I want to stop anyone from inheriting this class.

Since C++11, you can simply use final to prevent a class from being sub-classed further:

class BaseClass { };

class DoNotInheritClass final : public BaseClass { };

For limiting the number of sub-classes from a single base class, apparently there is no C++ built-in feature. You need to keep track of the sub-classes yourself by adding some static variable. Here's an existing answer: Counting instances of individual derived classes

artm
  • 17,291
  • 6
  • 38
  • 54
  • I need to inherit from base class once. Hence this would not help. This would not allow anyone to inherit from base class even once. – user2033594 Jan 07 '19 at 04:52
  • so you want to inherit from `BaseClass` just once, and no further down, right? – artm Jan 07 '19 at 04:53
  • No.. Moreover I want it to be generic as mentioned in question. Lets say I want base class to be inherited twice or thrice then what would be the approach – user2033594 Jan 07 '19 at 04:54
  • see this answer then https://stackoverflow.com/questions/772655/counting-instances-of-individual-derived-classes – artm Jan 07 '19 at 05:00
0

Here are some ideas that could help if you can't use the PIMPL solution from the other answer. They are either based on CRTP or on constructor tagging:

#include <type_traits>

struct A;

template<typename T>
struct Base final {

};

// Specialise Base for A to be non-final
template<>
struct Base<A> {};

struct A : Base<A> {};

The idea behind the first snippet is to have a final CRTP-base and add a non-final specialisation for class A. Obviously this allows users (or yourself) to define more allowed derivations if needed, but prevents accidental inheritance.

template<char...>
struct password {};

struct Base2 {

    Base2() = delete;

    template<char... pwd>
    Base2(password<pwd...> ) {
        using expected_pwd = password<'t','o','p','s','e','c','r','e','t'>;
        static_assert(std::is_same_v<password<pwd...>, expected_pwd>);
    }
};

struct A2 : Base2 {

    A2() : Base2(password<'t','o','p','s','e','c','r','e','t'>{}) {}
};

struct A3 : Base2 {

    // No way to construct Base2 without correct password :)
    A3() : Base2(password<'b', 'a', 'm', 'm'>{}) {}
};

The idea behind this second snippet (which is more a joke than real code...) is to replace the default constructor of the Base2 class by a password struct. Within the implementation you check the password given to the constructor. In the implementation of your derived class you simply call the Base2 constructor with the correct password. Of course, your users can derive from the base class but as the password is completely hidden in the implementation, there is no way to construct the derived objects :)

int main(){

    auto a = A{};
    auto a2 = A2{};
    auto a3 = A3{};  // fails
    return 0;
}
florestan
  • 4,405
  • 2
  • 14
  • 28