Home > other >  How to restrict access to the most direct base class, while still exposing the base-base classes?
How to restrict access to the most direct base class, while still exposing the base-base classes?

Time:09-20

I have a class hierarchy similar to this:

class Widget {
    // a lot of virtual members
};

class Button : public Widget {
    // new stuff   overrides
};

class MySuperButton : public Button {
    // ...
};

And I would like to hide the fact that MySuperButton inherit from Button, but not from Widget. Basically making the inheritance from Button private while keeping all its base classes public.

Why?

I have a complicated widget build on Button, which needs to maintain some invariant with its button state. Exposing it has a Button might allow something to modify the button directly breaking these invariants.

Example:

MySuperButton button;
button.setText("Click me!") // calls Button::setText
// Oh no, MySuperButton set some special text which has now been overriden =(

What doesn't work

  • Making MySuperButton inherit from Button privately also hides Widget, preventing me from doing Widget things with my button.

  • Using access specifiers does not prevent MySuperButton to be converted into a Button. So void doButtonStuff(Button& b); will accept a MySuperButton& just fine.

  • Using compositon forces me to reimplement a bunch of stuff that Button already reinmplements, just to forward it which is a PITA. Especially since the actual hierarchy is rather deep and these are big classes.

  • Virtual inheritance doesn't seem to work as the base isn't visible (not sure why that would be a problem though). See Godbolt

I can not modify the Button or Widget classes as they are from an external library (Qt in this case). Also the actual code is somewhat more complicated, the provided hierarchy is for illustration.

Is there any way to do this, or do I need to accept that my widget can be broken if I am not careful ?

CodePudding user response:

What you are asking is not really possible.

A possible Qt-specific solution is the following:

class MySuperButton : public Widget {
public:
    MySuperButton () {
        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(button = new Button());
        setLayout(layout);
    }

private:
    Button *button;
}
  • Related