C++ interface class causes ambiguous function call (Qt) - c++

This may be due to me not entirely understanding how interfaces in C++ work, but here we go:
I have base interface for a property class in QT5.
class IBaseProperty
{
public:
virtual ~IBaseProperty() {}
// Returns the property key as a string.
virtual QString getKey() = 0;
// Returns the property value as a raw string.
virtual QString getValueRaw() = 0;
// Sets the property key as a string.
virtual void setKey(QString key) = 0;
// Sets the property value as a raw string.
virtual void setValueRaw(QString value) = 0;
};
I also have a templated interface extension to make it easier to subclass properties that handle more specific data types.
template <class T>
class IProperty : public IBaseProperty
{
public:
virtual ~IProperty() {}
// Classifies a property with a Property_t identifier.
virtual Property_t getPropertyType() = 0;
// Returns the property value as the specified type.
// Bool is true if conversion was successful.
virtual T getValue(bool* success) = 0;
// Sets the property value as the specified type.
virtual void setValue(T value) = 0;
// Returns whether the current value can be converted correctly
// to the specified type.
virtual bool canConvert() = 0;
};
My base property (implementing only IBaseProperty) looks like this:
class BaseProperty : public QObject, public IBaseProperty
{
Q_OBJECT
public:
explicit BaseProperty(QObject *parent = 0, QString key = "", QString value = "");
virtual QString getKey();
virtual QString getValueRaw();
public slots:
virtual void setKey(QString key);
virtual void setValueRaw(QString value);
protected:
QPair<QString, QString> m_Property; // KV pair this property holds.
};
I subclass this to make a string property - obviously the base property can just return strings, but I wanted to keep the same function format between string/int/float/etc. properties by allowing getValue in all of them. GetValue in this case simply calls getValueRaw to return the value.
class StringProperty : public BaseProperty, public IProperty<QString>
{
Q_OBJECT
public:
explicit StringProperty(QObject *parent = 0, QString key = "", QString value = "");
virtual inline Property_t getPropertyType() { return Prop_String; }
virtual QString getValue(bool* success);
virtual bool canConvert();
public slots:
virtual void setValue(QString value);
};
The ambiguity occurs when I implement getValue and setValue:
inline QString StringProperty::getValue(bool* success)
{
*success = canConvert();
return getValueRaw(); // This line causes the ambiguity.
}
The compiler complains:
C2385: Ambiguous access of 'getValueRaw': could be the 'getValueRaw'
in base 'BaseProperty' or could be the 'getValueRaw' in base
'IBaseProperty'.
I'm not entirely sure what to do in this situation - I would have thought that IBaseProperty being a pure virtual class would mean that the function would not be able to be called from this point anyway, so would only be called from where it was implemented (BaseProperty). What would be the correct course of action to take to fix this? I'm not sure from which base class I should be calling the function.

For the first look, it seems to be classical diamond problem or diamond inheritance
String property inherits from BaseProperty and IProperty, and both of them have same base class IBaseProperty. That's why there is an ambiguity.

The problem is that a StringProperty contains two base class subobjects of type IBaseProperty. You probably want just one IBaseProperty, in which case you need to use virtual inheritance. (It's often a good idea for "interfaces" to be virtual base classes.)
template <class T>
class IProperty : public virtual IBaseProperty
{ /*...*/ };
class BaseProperty : public virtual IBaseProperty, public QObject
{ Q_OBJECT; /*...*/ };
class StringProperty : public virtual IProperty<QString>, public BaseProperty
{ Q_OBJECT; /*...*/ };
Recommended reading: C++ FAQ 25.8 through 25.15.

Related

What is the most generic way to link two independent classes without extra code?

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.

How to bind to OnItemSelectionChanged of a list view

In Unreal Engine 4, I want to bind an event to UListView::OnItemSelectionChanged. That event FOnItemSelectionChanged requires a NullableItemType, so I'm passing a pointer to the list entry class of the list view (my custom class derived from IUserObjectListEntry) as parameter.
UCLASS()
class PROJECT_API UMyListViewEntry : public UUserWidget, public IUserObjectListEntry
{
GENERATED_BODY()
// Members and functions don't matter here.
};
UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
GENERATED_BODY()
void NativeConstruct() final
{
MyList->OnItemSelectionChanged.AddDynamic(this, &UMyUserWidget::MyEventCallback);
}
void MyEventCallback(UMyListViewEntry* e)
{
// implementation details
}
private:
UPROPERTY(meta = (BindWidget))
UListView* MyList;
};
However, the AddDynamic() call causes the error
C2228: Left of ".__Internal_AddDynamic" has to be in a class/structure/union
so I suppose, the signature of the callback function I want to bind (the MyEventCallback()) is wrong.
What would be the correct signature for a function which should be bound to UListView::OnItemSelectionChanged?
It is not only about the signature of the callback, but also about how to add the callback.
Option #1: Use return value of OnItemSelectionChanged (the callback will be limited to UObject)
In UListView, its member OnItemSelectionChanged is implemented via a macro IMPLEMENT_TYPED_UMG_LIST, which does
virtual FOnItemSelectionChanged& OnItemSelectionChanged() const override { return OnItemSelectionChangedEvent; }
So to add a callback function to the delegate, use the return value:
UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
GENERATED_BODY()
void NativeConstruct() final
{
auto event = MyList->OnItemSelectionChanged();
event.AddUObject(this, &UMyUserWidget::MyEventCallback);
}
void MyEventCallback(UObject* e)
{
// implementation details, cast e to UMyListViewEntry*
}
// ...
};
You are limited to callbacks having UObject* as parameter (UListView is a specialization of its base classes using UObject as entry type).
The delegate which is available in blueprint (BP_OnItemSelectionChanged) can't be used, since it is private.
Option #2: Define custom delegate
If you want to use your custom entry type directly as parameter in the callback, you either could
implement your own list view or
derive from UListView and call a custom delegate in virtual void OnSelectionChangedInternal(UObject* FirstSelectedItem)
While the first approach is similar to the UListView implementation, the second approach is very short and might look similar to BP_OnItemSelectionChanged:
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnMyListItemSelectionChanged, UMyListViewEntry*, bool);
UCLASS(meta = (EntryInterface = UserObjectListEntry, EntryClass = UMyListViewEntry))
class PROJECT_API UMyListView : public UListView
{
GENERATED_BODY()
public:
FOnMyListItemSelectionChanged OnMyListItemSelectionChanged;
private:
void OnSelectionChangedInternal(UObject* FirstSelectedItem) override
{
Super::OnSelectionChangedInternal(FirstSelectedItem);
auto entry = Cast<UMyListViewEntry>(FirstSelectedItem);
OnMyListItemSelectionChanged.Broadcast(entry, entry != nullptr);
}
};
UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
GENERATED_BODY()
void NativeConstruct() final
{
MyList->OnMyListItemSelectionChanged.AddUObject(this, &UMyUserWidget::MyEventCallback);
}
void MyEventCallback(UMyListViewEntry* e, bool isSelected)
{
// implementation details
}
private:
UPROPERTY(meta = (BindWidget), meta = (EntryClass = UMyListViewEntry))
UMyListView* MyList;
};

How to refer to instances of a class universally without type codes?

I was making a text based RPG in which I have an abstract Item class. From this Item class, I have the classes Weapon, Potion, Key, and Armor. The main character class, Protagonist uses these items and has a function doItemEffect(Item*). How do I implement doItemEffect(Item*) in a way that I refer to all items in universally? To better phrase my problem, if I wasn't clear, here is an example that uses a quite ugly solution.
class Protagonist
{
public:
void doItemEffect(Item* it)
{
switch(it->getType()) //<-- The type is an enum class
{
case ItemType::WEAPON:
attackOpponent(it.getAttackPower()); //If it is a weapon it would have this function
break;
case ItemType::POTION:
heal(it.getHealPower()); //If it is a weapon it would have this function
break;
case ItemType::KEY:
//..Code..
break;
case ItemType::ARMOR:
//More Code...
break;
}
};
And an example of two of the classes Potion and Weapon (The type of the class is a private variable stored in Item with a mutator method setType()):
class Potion : public Item
{
int healPower;
public:
Potion(std::string name, std::string description) : Item(name, description)
{
setType(ItemType::POTION);
}
//Code
};
Weapon:
class Weapon : public Item
{
int attackPower;
public:
Weapon(std::string name, std::string description) : Item(name, description)
{
setType(ItemType::WEAPON);
}
//Code
};
As you can see, this code relies on an class code and a switch in the Protagonist class. Because of this, this doesn't seem very object oriented or polymorphic. Thus, is there a way I could get what subclass a type of Item is, without having to use class codes? Or is there any other solution? The other problem with this snippet above is also that whenever I refer to an item outside of its class, I have to use the same switch statement for each type of item.
Create a virtual function use() in your Item class. Override this function from your derived classes to trigger the various actions (attack, heal, etc.), so that all your subclassed items have an abstract interface to use/apply them.
You can either use RTTI (e.g. dynamic_cast<>()) as an alternative to a dedicated type field:
class Protagonist
{
public:
void doItemEffect(Item* it)
{
Potion *potion = dynamic_cast<Potion *>(item);
Weapon *weapon = dynamic_cast<Weapon *>(item);
if (potion != nullptr) {
heal(potion->getHealPower());
}
else if (weapon != nullptr) {
attackOpponent(weapon->getAttackPower());
}
or use polymorphism by adding a virtual effect() class member function in the abstract Item class:
class Item {
// ...
public:
virtual void effect(Protagonist *) = 0;
// ...
};
and overriding it in the derived classes:
class Potion : public Item
{
// ...
public:
void effect(Protagonist *) override;
};
which has the drawback that your Potion class needs to know that it can be used by a Protagonist. To remedy this, double dispatch is often used. The problem being that C++ does not support double dispatch as a language feature. It can be simulated using the visitor pattern as such:
class Weapon;
class Potion;
class DispatchReceiver {
public:
virtual void effect(Weapon *) = 0;
virtual void effect(Potion *) = 0;
};
class Item {
// ...
public:
virtual void effect(DispatchReceiver *) = 0;
// ...
};
class Potion : public Item {
// ...
virtual void effect(DispatchReceiver *dr) override
{
dr->effect(this);
}
// ...
};
class Weapon : public Item {
// ...
public:
virtual void effect(DispatchReceiver *dr) override
{
dr->effect(this);
}
// ...
};
class Protagonist : public DispatchReceiver {
// ...
public:
void effect(Weapon *weapon) override
{
attackOpponent(weapon->getAttackPower());
}
void effect(Potion *potion) override
{
heal(potion->getHealPower());
}
void doItemEffect(Item* it)
{
it->effect(this);
}
};
Have a list of item types
template<class...Types>
struct type_list_t{};
using Items=type_list_t<Potion, Weapon, etc>;
this replaces your enum. You can write get index of type, and get type from (compile time) index. You can even write what I call a magic switch, mapping runtime (bounded) index to a compile time type via continuation passing style.
Next add a visit method to Item. It takes a index into the type list and then static casts this to the type of the child, then invokes a passed-in callback with the result of the cast.
Write function overloads that look like this:
void use_item( Protagonist*, Potion* );
void use_item( Protagonist*, Weapon* );
Then dispatch to it using visit in Protagonist.
Now you can simplify this by using a pre written variant.
template<class Base, class...Ts>
struct poly_variant:boost::variant<Ts...>{
using boost::variant<Ts...>::variant;
Base& base();
Base const& base() const;
};
now you can visit in Protagonist. A variant of this can be used if you want to make the storage be a pointer (or a smart pointer).
Write base() via apply visitor.

QMetaObject::invokeMethod: No such method when using inheritance

I have got a super class Common, which inherits from QObject. Then I have got a class Item, which inherits from Common.
Common.h
class Common : public QObject {
Q_OBJECT
public:
// some methods
};
Item.h
class Item : public Common {
Q_OBJECT
public:
// some methods
void test(QString value);
};
Item.cpp
void Item::test(QString value) {
qDebug() << value;
}
I want to use QMetaObject::invokeMethod to dynamically call a function.
So I implemented a test function in the Item class, which takes exactly one string.
Item* item = new Item();
QMetaObject::invokeMethod(item, "test", Qt::DirectConnection, Q_ARG(QString, "1234"));
This does not work. I get the following error: QMetaObject::invokeMethod: No such method Common::test(QString), which is perfectly okay and fine, because the Common class has no test function.
How can I tell QMetaObject::invokeMethod, that it should call the method from the Item class?
QMetaObject::invokeMethod can only invoke methods known to the Qt meta object system. These are slots and "invokable" functions, the latter being functions with the keyword Q_INVOKABLE before them.
So either write:
class Item : public Common {
Q_OBJECT
public slots:
// ^^^^^
void test(QString value);
};
or:
class Item : public Common {
Q_OBJECT
public:
Q_INVOKABLE void test(QString value);
//^^^^^^^^^
};

access protected variable - complicated situation with inheritance and sub-classes

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.