Making Button classes more inheritance-friendly


#1

Hi Jules,

We’ve created subclasses of some of the Button classes. To achieve our desired results, we’ve had to modify JUCE code, which I’m hoping you can integrate into your source tree. We have three requests, with explanations below:

(1) Add a default String::empty argument to Button’s constructor
(2) Declare all JUCE Button subclasses’ destructors as virtual
(3) Declare all JUCE Button subclasses as virtual derivatives of Button

Now, to explain…

(1) If I try to compile the following class declaration with constructor definition:

class MyImageButton : public ImageButton
{
public:
    MyImageButton (const String& name) : ImageButton(name) {}
    // assume we've added other custom stuff here...
};

I get compiler error “[color=#0000FF]‘juce::Button::Button’ : no appropriate default constructor available[/color]”. To get rid of this, I have to provide the Button constructor with a default argument, i.e. changeexplicit Button (const String& buttonName);toexplicit Button (const String& buttonName = String::empty);
(2) ImageButton’s destructor should also be declared virtual, so an ImageButton pointer can be used to delete a MyImageButton object.

(3) Assuming I’ve addressed (1) & (2), suppose I declare a custom class MyButton with additional functionality:

class MyButton : public Button { public: MyButton(const String& buttonName, bool isSticky) : Button(buttonName), mIsSticky(isSticky) {} void setSticky() {bool b} { mIsSticky = b; } private: bool mIsSticky; };
Then I want to declare a new class, MyToggleButton, which inherits both from ToggleButton (to get all the ToggleButton behavior) AND MyButton (to get MyButton::setSticky()):

class MyToggleButton : public ToggleButton, public MyButton { public: MyToggleButton(const String& buttonName) : MyToggleButton(buttonName) {} void func() {} };
This will yield multiple-inheritance ambiguity errors when compiled. To fix that, juce::ToggleButton must be declared as a virtual derivative of Button, e.g. by changing

(As an aside, I did consider using a Decorator design pattern, but decided it wouldn’t work for reasons I don’t remember at the moment…)

Thanks!
B


#2

Ok…

  1. Eh? No, the base class definitely does not need a default constructor. You’re probably just misunderstanding the error message - try declaring a private copy constructor and assignment operator to prevent the compiler attempting to generate them for you.

  2. aaaghhh, deja-vu! It seems like every few days I find myself answering this same piece of nonsense!! An inherited virtual method is always virtual, the keyword is optional in subclasses!

  3. Yes, C++ will allow you to create diamond-shaped inheritance patterns, in the same way that a brick will allow you to hit yourself in the face with it. But to save people from their more insane impulses, I’ve no intention of allowing any of my classes to be used like that, and will never declare them as public virtual. Just the thought of trying to combine two different Components into one class makes me feel queasy…