This is my first post on stackoverflow so be gentle :)
I have standard diamond problem but I'd managed to sort it out.
class Control
{
public:
bool Focused;
};
class Caption : public virtual Control
{
public:
string Text;
};
class Frame : public virtual Control { };
class Textbox : public Caption, public Frame, public TextEditor { };
Sadly another problem with inheritance appeared. Class TextEditor has common variable names:
class TextEditor
{
public:
bool Focused;
string Text;
};
Compiler gives me errors:
ambiguous access of 'Text'
ambiguous access of 'Focused'
But all I want is those variables from all classes to be merged in derived class 'Textbox'.
Here's link to the UML picture with the problem
Thanks for any kind of help
Sorry for any languages mistakes and/or question I'm asking.
Update
A little explanation cause I might have use wrong words. Sorry for that.
By 'merge' I meant that:
If I use variables or methods of Control, Caption or Frame it will influence the values of TextEditor and vice versa. In other words variables are shared in derived class.
So my final class will look like this:
class Textbox : public Caption, public Frame, public TextEditor
{
public:
string Text;
bool Focused;
};
And not like this:
class Textbox : public Caption, public Frame, public TextEditor
{
public:
string Caption::Text;
bool Caption::Focused;
string TextEditor::Text;
bool TextEditor::Focused;
};
Which happening right now. Cause I can't do this:
Textbox A;
A.Text = "Text";
Because I have two variables with the name Text. So I would have to do this:
Textbox A;
A.Caption::Text = "Text";
A.TextEditor::Text = "Text";
Best regards
Lavi
Notes:
Consider using mutator methods
Please http://sscce.org/ - your example seems a bit over the show - would be easier to give you a clear example of how to solve your problem if your example in the problem was infact sscce. Either way, its still sufficient and your problem is clear enough I guess.
Answers:
Why does class TextEditor not also inherit from class Control and class Caption ? This would seem like the obvious solution - you would have to use virtual inheritance for class TextBox still though.
If 1 is not an option - then there is this - but in this limited sample HasText and Focusable seems to be pointless when compared to Caption and Control respectively.
class HasText
{
public:
virtual string& text() { return text; }
virtual const string& text() const { return text; }
private:
text
};
class Focusable
{
public:
virtual bool& focused() { return focused; }
virtual const bool& focussed() const { return focussed; }
};
class Control : public virtual Focusable { };
class Caption : public virtual Control, public virtual HasText { };
class Frame : public virtual Control { };
class TextEditor : public virtual HasText, public virtual Focusable { };
class Textbox : public virtual Caption, public virtual Frame, public virtual TextEditor { };
Related
There's a hierarchy of classes describing different properties of some object. The abstract class Property is a base class, and it has children: IntegerProperty, BooleanProperty, and so on. All data is encoded in QString and derived classes decode it in their own way.
class Property : public QObject
{
Q_OBJECT
public:
// ...
virtual QString value() const = 0;
virtual bool setValue(const QString &value) = 0;
virtual bool validateValue(const QString& value) = 0;
// ...
};
class IntegerProperty : public Property
{
// ...
virtual QString value() const override;
virtual bool setValue(const QString &value) override;
virtual bool validateValue(const QString& value) override;
// ...
};
// ...
Every property class must have an independent editor (GUI widget) - PropertyEditor (abstract class again), IntegerPropertyEditor, BooleanPropertyEditor, and so on.
class PropertyEditor : public QWidget
{
Q_OBJECT
public:
inline Facer::PropertyPointer attachedProperty() { return m_property; }
protected:
PropertyEditor(Facer::PropertyPointer attachedProperty, QWidget* parent = nullptr);
virtual void mousePressEvent(QMouseEvent* event) override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
// ...
};
class IntegerPropertyEditor : public PropertyEditor
{
// ...
};
// ...
For example, I have a set of different properties. I don't know which exactly properties I have because they are all pointers to Property class. My task is to create specified editors of these properties, so I need to get IntegerPropertyEditor if the property object is IntegerProperty.
for (Property* property : propertySet())
PropertyEditor* editor = createEditor(property);
I made a temporary workaround with macro:
#define IF_TYPE_GET_EDITOR(propertyType, editorType) \
if (std::dynamic_pointer_cast<propertyType>(property)) \
return new editorType(property, this);
// ...
PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
IF_TYPE_GET_EDITOR(BooleanProperty, BooleanPropertyEditor)
else IF_TYPE_GET_EDITOR(ColorProperty, ColorPropertyEditor)
else IF_TYPE_GET_EDITOR(FloatingPointProperty, FloatingPointPropertyEditor)
else IF_TYPE_GET_EDITOR(FontProperty, FontPropertyEditor)
else IF_TYPE_GET_EDITOR(IntegerProperty, IntegerPropertyEditor)
else IF_TYPE_GET_EDITOR(TextProperty, TextPropertyEditor)
else throw std::runtime_error("This PropertyType is not implemented yet");
}
It doesn't look like a good solution - if I add a new type of property and its editor, I'll have to update this code as well. What is the most convenient and generic way to link an editor class and a property class?
This might give some extra code, especially depending on how your project is set up, but one solution is to make a virtual function in Property that returns a pointer to an editor:
class Property : public QObject
{
public:
virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
// let's put our default behavior here
throw std::runtime_error("This PropertyType is not implemented yet");
}
//...
};
Now, you make each class responsible for supplying its own editor:
class IntegerProperty : public Property
{
public:
// doesn't have to be virtual, I don't think Just a regular version should be fine too.
virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
return new IntegerPropertyEditor(this, widget);
}
//...
};
Depending on how many classes you have, that may be a lot of copying and pasting.
However, the fun part is PropertySetWidget::create():
PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
return property->CreateEditor(this);
}
Because every child of property is responsible for supplying its own editor, we don't have to worry about it at this level. If one doesn't exist/isn't implemented, property::CreateEditor() will throw an error for you. If one does exist/is implemented, it will return a pointer to a new instance the editor automatically.
The big advantage is that if you add a new property and its editor, you don't have to touch it this function at all. The virtual function takes care of properly implementing it for you. If the new property has an editor, it just needs to overload that function, and this create() still works properly.
Of course, you will have to modify Property's interface this way, which may not be feasible in your case. That's the major drawback to this approach.
What you want requires Reflection implemented, although there are rather cumbersome and ugly ways to implement what you wanted without macros. I personally recommend the solution of #Chipster.
If you are still interested in methods that do not require Property to provide its own editor... I wrote an example, you can check it out.
#include <iostream>
#include <memory>
class A
{ //virtual working class
public:
virtual ~A() = default;
};
//two possible implementations
class B : public A {};
class C : public A {};
//Editor interface
class EditorA
{
public:
virtual ~EditorA() = default;
virtual void print() = 0;
};
//Implementations of editors
class EditorB :
public EditorA
{
public:
void print() override
{
std::cout << "Editor B\n";
}
};
class EditorC :
public EditorA
{
public:
void print() override
{
std::cout << "Editor C\n";
}
};
//template class used for declaring which Editor you use depending on the class you provide
// I would make a namespace but there are no template namespaces
template<typename T>
class EditorT;
template<>
class EditorT<B>
{
public:
using EditorType = EditorB;
};
template<>
class EditorT<C>
{
public:
using EditorType = EditorC;
};
using namespace std;
// Recursive GetEditor code... written inside class as a static method for reasons.
template<typename... Args>
class CEditorIdentifier;
template<>
class CEditorIdentifier<>
{
public:
static EditorA * GetEditor(shared_ptr<A>& val)
{
return nullptr;
}
};
template<typename Arg, typename... Args>
class CEditorIdentifier<Arg, Args...>
{
public:
static EditorA * GetEditor(shared_ptr<A>& val)
{
if(std::dynamic_pointer_cast<Arg>(val))
{
return new typename EditorT<Arg>::EditorType;
}
return CEditorIdentifier<Args...>::GetEditor(val);
}
};
template<typename... Args>
EditorA* FindEditor(shared_ptr<A>& val)
{
return CEditorIdentifier<Args...>::GetEditor(val);
}
int main()
{
shared_ptr<A> b = make_shared<B>();
shared_ptr<A> c = make_shared<C>();
EditorA* eB = FindEditor<B,C>(b);
EditorA* eC = FindEditor<C,B>(c);
eB->print();
eC->print();
return 0;
}
Now you can add additional classes D,E,F... you only have to maintain the reference classes EditorT<D>, EditorT<E>, EditorT<F>...
Complicated right? Well... current features in C++ for such programming are limited. It's being worked and will be available in the future (see Reflection TS) but not now. Also it will be simpler to implement in C++20 with all the extensions to constexpr.
I like the answer above about each Property having a virtual method to return the appropriate type of editor. The only downside to that is that it may tie user interface-related elements into your lower-level code. Depending on your needs, that may or may not be OK.
A variation of your original factory that keeps the editor creation separate from the property class definitions is that you could add a "propertyType" virtual method that returns an integer, and then your factory becomes a switch statement:
switch (Property.propertyType ())
{
case BooleanPropertyType: create Boolean property editor
case StringPropertyType: create String properly editor
etc.
}
You would have an enum somewhere with the defined property type values. It's the same basic idea, but it avoids the overhead of the dynamic cast. (Whether or not it's actually faster is something to test.)
I don't think there's anything fundamentally wrong with your approach other than the possible dynamic_cast overhead, and often, I think that having a factory method where all of the editors are created for all of the types can be easier to maintain than creating the UI elements in classes where you're trying to manage data. Purists may see this as a violation of good object oriented classes, but it really depends on your needs and who you're trying to please.
I got problems formulating it precisely so I left more general description in the title (if you have more precise description of the problem, please comment, I'll edit the title).
The problem: Two classes AudioStream and VideoStream are derived from base class MediaStream which has some common for audio and video stream methods, but is not intended to be used as-is. Consequently, there are two classes AudioStreamSettings and VideoStreamSettings which are derived from MediaStreamSettings and passed to the constructors of their corresponding stream classes. MediaStreamSettings stores settings common for audio and video, and base class MediaStream accesses this data. The question is: what would be the best way to design this hierarchical relationship between base classes of streams and settings?
I can think of a quick solution like the following:
class MediaStream {
public:
MediaStream(const MediaStreamSettings& settings){
// do nothing, let derived classes initialize settings_
// note: I feel guilty for doing this...
}
virtual ~MediaStream(){}
protected:
std::shared_ptr<MediaStreamSettings> settings_;
};
class VideoStream : public MediaStream {
public:
VideoStream(const VideoStreamSettings& settings):
MediaStream(settings)
{
settings_ = std::make_shared<VideoStreamSettings>(settings);
}
void doSomething(){
int s1 = std::dynamic_pointer_cast<VideoStream, MediaStream>(settings_)->getVideoStreamSetting1();
...
}
};
class AudioStream : public MediaStream {
public:
AudioStream(const AudioStreamSettings& settings):
MediaStream(settings)
{
settings_ = std::make_shared<AudioStreamSettings>(settings);
}
}
To summarize I'm not comfortable with two things in this approach:
not initializing settings_ in base class (should I make it abstract to calm myself?)
using dynamic_pointer_cast every time I need to access settings in derived classes (should I make a method wrapper for this?)
One solution is to not store data in MediaStream and add a virtual method
virtual const MediaStreamSettings& GetMediaStreamSettings() const = 0;
Since MediaStream should not be used as-is, making it an abstract class should be acceptable (and desirable).
Thus providing implementation (which includes class members) is pointless.
class IMediaStream {
public:
virtual ~IMediaStream() {}
virtual void play() = 0;
virtual std::shared_ptr<MediaSettings> getSettings() = 0;
private:
IMediaStream() {}
};
template<Setting>
class MediaStream : public IMediaStream {
public:
MediaStream(const Setting& settings){
settings_ = std::make_shared<Setting>(settings);
}
virtual ~MediaStream() {}
virtual void play() override {
// Implementation here
}
virtual std::shared_ptr<MediaSettings> getSettings() override {
return std::dynamic_pointer_cast<Setting, MediaSettings>();
}
private:
std::shared_ptr<Setting> settings_;
}
// Alternatively you can inherit or specialize
// the template to add your implementation
typedef MediaStream<VideoStreamSettings> VideoStream;
typedef MediaStream<AudioStreamSettings> AudioStream;
Hmm... I'm trying to break down my problem...
There is a library with some classes that do almost what I want. I can't change classes of the library so I want to derive them and change what I need.
In this case there is a derived class in the library with two subclasses. Now I derive the class and the subclasses.
In the second sub-class there is a virtual method witch modifies a protected variable from the first sub-class.
I want to override the virtual method with a new virtual method which calls the old virtual wethod an then modify the protected variable again.
Why am I getting the error in mySubClass2 while accessing fResponse?
How can I solve my problem?
class libraryClass : pulic someLibraryBaseClass {
protected:
libraryClass::librarySubClass2 lookUpFunction(int ID) {
//some magic to find the obj
return obj;
}
public:
class librarySubClass2;
class librarySubClass1 {
public:
librarySubClass1(libraryClass baseObj) {
myBaseObj = baseObj;
}
void someCallingFunction(int ID) {
libraryClass::librarySubClass2 obj = myBaseObj->lookUpFunction(ID)
obj->someHandleFunction(this)
cout << fResponse;
}
protected:
friend class librarySubClass2;
unsigned char fResponse[200];
private:
libraryClass myBaseObj;
};
class librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
snprintf((char*)obj->fResponse, sizeof obj->fResponse, "Some Text...\r\n"
}
};
};
class myDerivedClass : public libraryClass {
public:
class mySubClass2 : public libraryClass::librarySubClass2;
class mySubClass1 : public libraryClass::librarySubClass1 {
protected:
friend class mySubClass2;
};
class mySubClass2 : public libraryClass::librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
libraryClass:librarySubClass2::someHandleFuntion(obj);
snprintf((char*)obj->fResponse, sizeof obj->fResponse, "Add some more Text...\r\n"
}
};
};
Edit: Forgot * in Method of mySubClass2
Possible solution:
class mySubClass2 : public libraryClass::librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
libraryClass:librarySubClass2::someHandleFuntion(obj);
myDerivedClass::mySubClass1* nowMyObj = (myDerivedClass::mySubClass*) obj;
snprintf((char*)nowMyObj->fResponse, sizeof nowMyObj->fResponse, "Add some more Text...\r\n"
}
};
Now I derive the class and the subclasses.
In your example code, you're only deriving the main class and not the subclass. You have to inherit also the subclass:
class libraryClass : pulic someLibraryBaseClass
{
class librarySubClass1 : public someLibraryBaseClass::someLibrarySubClass1 { };
// ....
};
But that can be done only if the subclass is accessible (protected/public).
As far as I can tell you wonder why you can't access obj->fResponse in
void mySubClass2::someHandleFunction(libraryClass::librarySubClass1 obj) { ... }
Well, obj is of type librarySubClass1 which inherits its share of fResponse from the common ancestor. However, that is the share of a relative of mySubClass2, not yours as you are mySubClass2! You can only access the fResponse member of objects which are known to be of type mySubClass which actually happens to be known to be not the case for a librarySubClass1 object.
Getting access to librarySubClass::fResponse is as if you got free access to your uncle's inheritance from your grandparents. Unless you have a very unusual family sharing its wealth freely among all family members, you probably won't have access to your uncle's inheritance either.
Because fResponse in mySubClass2 is treated as protected and at that point it is outside of libraryClass, it only worked on librarySubClass2 because it is inside libraryClass.
The application defines 3 interfaces to be implemented in a plug-in. Widget is always the base.
// Application code...
class Widget {
virtual void animate() = 0;
};
class BigWidget : public Widget {
};
class SmallWidget : public Widget {
};
Every interface implementation is derived from NiceWidget which provides some plug-in internal common information.
// Plug-in code...
class NiceWidget {
// nice::Thing is only known in plug-in code.
nice::Thing thing();
};
class NiceBigWidget : public NiceWidget, public BigWidget {
void animate() override;
};
class NiceSmallWidget : public NiceWidget, public SmallWidget {
void animate() override;
};
func is called from application code. wid is known to be implemented by this plugin. Thus wid is also a NiceWidget. The goal of func is to call the thing method of it.
// Plugin-in code...
void func(Widget* wid) {
// wid is either NiceBigWidget or NiceSmallWidget.
auto castedBig = dynamic_cast<NiceBigWidget*>(wid);
if (castedBig) {
castedBig->thing().foo();
return;
}
auto castedSmall = dynamic_cast<NiceSmallWidget*>(wid);
if (castedSmall) {
castedSmall->thing().foo();
return;
}
assert(false);
}
But trying to cast wid to every Nice* can become very awful with increasing hierarchy size. Are there better solutions out there?
First: if you know that wid will always be a NiceWidget*, why not say so in func()? And you would not need a cast at all:
void func(NiceWidget* wid)
{
wid->thing().foo(); // Done
}
Even if you can't change the function signature for whatever reason, you would only need one cast:
void func(Widget* wid)
{
NiceWidget* casted = dynamic_cast<NiceWidget*>(wid);
if (casted)
casted->thing().foo();
else
throw std::exception(); // Well, throw the right exception
}
You can assert() instead of throwing an exception, of course, if you think it is better for your purposes.
In any case, you just need a pointer to the class that defines the functions you need to use (in this case, thing()), not to the most derived classes. If you will override the function in derived classes, make it virtual and you are done anyway.
If you know, that every NiceWidget is Widget, you should consider extending NiceWidget from Widget.
class Widget {
virtual void animate() = 0;
};
class BigWidget : public Widget {
};
class SmallWidget : public Widget {
};
class NiceWidget : Widget{
// nice::Thing is only known in plug-in code.
nice::Thing thing();
};
class NiceBigWidget : public NiceWidget, public BigWidget {
void animate() override;
};
class NiceSmallWidget : public NiceWidget, public SmallWidget {
void animate() override;
};
There will be another problem called The diamond problem, and it may be solved using virtual extending
After that it's should be OK to dynamic_cast from Widget to NiceWidget
I don't think this is possible, but if it is, I'd find it very usseful.
I'm making a Gui API where the user does the paint event. Lets say I want to make a Numeric TextBox. Well it would only seem good practice for it to inherit from TextBox. The problem with this, is that the user is then stuck to reimplement the paint event for the textbox since
TextBox::paint();
Would just call my default way of drawing it.
It would be annoying if they had to maintain all their TextBox derivatives.
Is there a way to get around this problem?
Lets say my TextBox paints a square, then the numeric part adds a circle, but the user's textbox, which derives from my TextBox draws a triangle, and my Numeric one derives from my TextBox I want the result to be triangle, circle.
Thanks
As I say in my comment, I think the bridge pattern is actually what you want, but since you're trying to insert a user's class as a base class for your NumericField thing the way you'd do THAT is to:
template < typename Base = TextField >
struct NumericField : Base
{
...
void paint() { Base::paint(); draw_circle(); }
};
Now the user could use NumericField<> or they could insert their class:
struct UserField : TextField
{
...
void paint() { draw_triangle(); }
};
NumericField<UserField> my_field;
The bridge answer would look more like so:
struct TextField
{
TextField() : extender_(new null_extender) {}
...
void set_extender(extender*);
virtual void paint() { draw_square(); extender_->paint(); }
...
};
struct extender { virtual void paint() = 0; };
struct null_extender { void paint() {}};
struct numeric_extender { void paint() { draw_circle(); }};
struct UserField
{
void paint() { draw_triangle(); extender()->paint(); }
};
Lots of details missing from that, but that would sort of be the story.
Isn't the only difference between NumericTextBox and TextBox that the former only allows the input of certain characters? Do you want it to paint differently?
I'm not sure quite what you mean. Your question is not that clear.
The title seems to be asking how to call the base class initializer or constructor,
is that what you want?
If this is what you want then just like this.
class TextBox
{
public:
TextBox() { }
virtual ~TextBox() { }
virtual Paint() { }
};
class NumericTextBox : public TextBox
{
public:
NumericTextBox() : TextBox() { }
~NumericTextBox() { }
};
Make sure the base class for TextBox::Paint and any other methods are declared virtual as well as the destructor.