Private intermediate inheritance

I've been working on a my own version of a graphic framework program and I've run into a problem with inheritance.

Every interesting class is of type "Drawable".
An other class is the Label class, which inherits from Drawable.
And the class in this question is the Button class. The button class is a Label that is clickable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Drawable
{
  virtual void draw()=0;
  virtual void click()=0;
  ...
};
class Label:public Drawable
{
  void draw() {/*Draw label*/};
  void click() {} /*Not clickable*/
  ...
}
class Button:public Label
{
  void draw() {/*Draw button with help of Label::draw*/}
  void click(); {/*Code when clicked*/}
  ...
}


However I want to hide the fact that a button is a label but i want is to still be a drawable. Like the following code:

1
2
3
4
Drawable *d1=new Label; //ok
Drawable *d2=new Button; //ok
Label *l1=new Label; //ok
Label *l2=new Button; //fail 


Private inheritance does not work since is would hide the Drawable class as well. I could solve this by declaring a Label object inside the Button class but that would require access methods to every label method. I would really like to use inheritance.

I'm also using the same technique to implement a Progress Bar

Any ideas?
"Button is Drawable and is implemented by Label" is translated to C++ as
class Button : public Drawable, private Label

If Drawable is an empty class, there is no additional overhead to inherit from it again (inheriting from an empty base class does not increase object size on most compilers), but because it has pure functions, it would have to be a virtual base:

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
#include <iostream>
#include <memory>
class Drawable
{
 public:
  virtual void draw()=0;
  virtual void click()=0;
};
class Label: public virtual Drawable
{
 public:
  void draw() { std::cout << "draw label\n"; }
  void click() { std::cout << "label clicked\n"; }
};
class Button: public virtual Drawable, private Label
{
 public:
  using Label::draw;
  void click() { std::cout << "button clicked\n"; }
};
int main()
{
    Label lp;
    lp.draw();
    lp.click();

    Drawable& dp = lp;
    dp.draw();
    dp.click();

    Button bp;
    bp.draw();
    bp.click();

    Drawable& dp2 = bp;
    dp2.draw();
    dp2.click();
}


Note that use of private inheritance to express "implemented-by" relationship is generally discouraged in favor of composition. It is only justified if Button needs to access protected members of Label or redefine virtual member functions of Label (see Scott Meyers, "Effective C++" item 42)
Topic archived. No new replies allowed.