class Button : public ClickableArea
{
...........
class ButtonListener : public ConcreteClickableAreaListener<Button>
{
virtual void OnEnter();
virtual void OnExit();
virtual void OnHover();
virtual void OnClick();
virtual void OnRelease();
};
};
Compiler gives me "warning C4510: 'ButtonListener' : default constructor could not be generated","'Button::ButtonListener' : no appropriate default constructor available"
Is it because ButtonListener is nested ? It worked fine in a non-template version.
The compiler is telling you exactly what the problem is. It's trying to generate a default constructor for ButtonListener, but it can't because ConcreteClickableAreaListener<Button> doesn't have a default constructor. Either give ButtonListener a constructor so the compiler won't try to generate a default constructor, or give ConcreteClicakbleAreaListner<> a default constructor.
Thanks, it just dawned on me that default means parameterless. I chose to add ConcreteClickableAreaListener(){} in the template, above error is gone but now I have a problem with instancing :
listener=new ButtonListener<Button>(this); gives " 'Button' : illegal use of this type as an expression "
listener=new ButtonListener(this); gives "No constructor could take the source type, or constructor overload resolution was ambiguous"
The first one doesn't work because ButtonListener isn't a template. The second one doesn't work because you didn't give ButtonListener a constructor that accepts a Button * as an argument.
Indeed it's not a template (what was I thiking), and I forgot this one: ButtonListener(Button* b):ConcreteClickableAreaListener<Button>(b){}; So it's ok now.
If you have a non-default constructor for the ButtonListener, you don't (unless there is another reason) need a default constructor for ConcreteClickableAreaListener any more. In general, when people give you an either/or for fixing a problem, a little thought is needed about which approach is more appropriate. Had you taken the other option first it would have worked right away. :)
But to think about this, a little background is needed. C++ generates a default constructor when you don't define any constructors at all. So a class has a default constructor either when you provide one explicitly, or when you expect C++ to provide one.
Providing a non-default constructor is a signal to C++ that default-constructing the class might not make sense. There are many classes for which this is true: there is no meaningful "default instance" of the class. This is a design decision that has to be thought about with every class. Does it make sense to define a ConcreteClickableAreaListener where no owner is specified? (If so, the logical thing to do with the 'owner' data member is to set it null in that constructor and check for null-ness everywhere else; but this can be annoying, so you don't want to allow for this if you don't have to.) How about a ButtonListener in particular? (In general, good design results in the same answer for both classes, because of the Liskov Substitution Principle - derived classes should be swappable for their bases as much as possible; they provide different behaviour, but the same interface.)