To prevent inheritance

Hi,
I got following question from one of friend,Could anyone provide me some input.

can we write a class whic can be inherit only by respective category.

supoose i have three classes. like bird and color and red.

Red class can inherit the color but if bird class try to inherit the color class
than it should get error.

I hope I have clarify my statement.
Last edited on
Hm.. your problem is not so clear to me..

Do you want to restrict class inheritance purely by the name of the class? Surely not.

So what is the difference between the class "bird" and the class "red" so that "bird" may not inherit from "color" while "red" is allowed to?
I don't really see the practical value of something like this, but here's something I came up with:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
template <class A, class B>
struct TypeList
{
    typedef A Value;
    typedef B Next;
};

template <class T>
struct FriendMaker { typedef T Type; };

template <class Base, class DerivedList, int DerivedCount>
class Uninheritable;

template <class Base>
class Uninheritable<Base, void, 0>
{
    friend class FriendMaker<Base>::Type;

    virtual ~Uninheritable(){}
};

template <class Base, class DerivedList>
class Uninheritable<Base, DerivedList, 1>
{
    friend class FriendMaker<Base>::Type;
    friend class FriendMaker<typename DerivedList::Value>::Type;

    virtual ~Uninheritable(){}
};

template <class Base, class DerivedList>
class Uninheritable<Base, DerivedList, 2>
{
    friend class FriendMaker<Base>::Type;
    friend class FriendMaker<typename DerivedList::Value>::Type;
    friend class FriendMaker<typename DerivedList::Next::Value>::Type;

    virtual ~Uninheritable(){}
};

//etc...

//======================================================================

class Color : virtual public Uninheritable<Color,
    TypeList<class Red, TypeList<class Blue, void> >,2> {};

class Red : public Color {};
class Blue : public Color {};
class Bird : public Color {};

int main()
{
    Color color;

    Red red;
    Blue blue;

    //uncommenting the following causes a compilation error

    //Bird bird;

    return 0;
}

Last edited on
@m4ster r0shi: *chrm*... erm... I'd call that... "eloquent" ;-).

While I don't see why you need virtual inheritence or the derived count. But then again.. I don't see why you need typelists for this either. ;)

Basically its based on the "name of the class", which is indeed probably not so usefull..

Simpler version for easier understanding what principle is used here (except that my version prohibits instances of "Color" as well and that r0shi uses the destructor, I am using constructor.):

1
2
3
4
5
6
7
8
9
10
11
12
class Color
{
  Color() {} // private constructor, so nobody can subclass it by default...
  // ...except these guys
  friend class Red;
  friend class Blue;
};

class Red : public Color {}; // OK. Red is a friend of Color.
class Blue : public Color {}; // ditto
class Bird : public Color {}; // nope! Bird is no friend so can't call the constructor of Color.
...

Well, I want to be able to create base class objects.
I wanted to provide a generic solution that doesn't have any unwanted side-effects.

Virtual inheritance is necessary here, as it makes derived classes have to call the
Uninheritable dtor directly (not through the base class), and this is what causes
the compilation error (the Uninheritable dtor is private to them).

And since this is a generic solution, I need a way to pass the set of
allowed derived types to the Uninheritable class. That's why I need the
DerivedList template param.

I wanted to make something that iterates through the typelist and befriends types as it goes,
but this doesn't seem possible :/ That's why I need the DerivedCount template param.

It's code you write once and can use always.
The only thing you have to add to your classes when
you define them is a line like the following, next to their name:

: virtual public Uninheritable<Base, DerivedList, DerivedCount >
Last edited on
owned!
The purpose of this question is to limited the scope of inheritance and also avoid the misuse of
inheritance. I took example color ,red ,bird classes . The intension of these classes to limit the
inheritance to its subcategory. like red can derived color class but bird does not come into
that category.

So anone whio write any class can inherit class to the respective category and get error if it tries to inherit class to diffirent category


Thanks a lot for you reply.


Last edited on
Yet, the question is: What makes the "categories" different to each other?

The current solutions presented are based on a specific list of names of the classes allowed to inherited (whereas m4ster r0shi's version is much stricter than mine, but still its based on an explicit enumeration of all names of classes).

If you categorize your classes by other things, the solution would have to look much different. For example, you could say that: "A class which subclasses 'Color' must provide a member function 'PaintHouse' to paint a house with its own colour."

The natural solution to this categorizing would be "abstract virtual functions" (also called "pure virtual functions").

This would make much more sense to me than just restricting the subclassing by listing names of classes.


@m4ster r0shi: Ah, I got the point with the virtual inheritance. You are trying to disallow sub-sub-classes? Nice usage ;). But that works only on the constructor and not the destructor, so you have to use a private constructor, right?

About the DerivedCount... Couldn't you specialize the Uninheritable for void to mark the end of the typelist instead and then subclass from the next item in the list? This would remove the need to add a template specialization for every possible typelist length as well as the need to specify the count of your types.

Hm.. on second thought, that won't work with the private constructor.

It is probably possible by using an own inheritance hierachy template of a helper class that only holds the type of the incomplete class it has to be friend with.. somehow... maybe? Or maybe not. Can't think of a working solution right now. But then again, I doubt restricting subclasses to a named list of classes is that usefull in practice anyway.


@ceruleus: Pardon?
Last edited on
imi wrote:
The natural solution to this categorizing would be "abstract virtual functions"
(also called "pure virtual functions"). This would make much more sense
to me than just restricting the subclassing by listing names of classes.

Agreed.

imi wrote:
Ah, I got the point with the virtual inheritance.

Though, to be honest, it wasn't me the one who came up with that;
I saw it somewhere on the net :P The FriendMaker workaround wasn't my idea either.

imi wrote:
About the DerivedCount...

The thing is that as long as inheritance prevention relies
on friendship there's not much you can do... :S

My guess is that a really useful way to do this would require
a completely different approach to the solution core.

imi wrote:
But then again, I doubt restricting subclasses to a named list of classes is that usefull in practice anyway.

Agreed.
Last edited on
This is a standard pattern (without the templates). It's quite impressive that m4ster r0shi came up with it independently.
Lol... I'd already seen before the way to prohibit inheritance completely for a class.

m4ster r0shi wrote:
Though, to be honest, it wasn't me the one who came up with that;
I saw it somewhere on the net :P The FriendMaker workaround wasn't my idea either.

The only thing I added here was the derived list.
@imi just trolling around... you guys should be more grateful of me imo
Why? Nobody likes trolls.
Topic archived. No new replies allowed.