无需额外代码即可链接两个独立类的最通用方法是什么?

尼基塔

有一个类层次结构,描述了某个对象的不同属性。抽象类Property是基类,它具有子类:IntegerPropertyBooleanProperty等等。所有数据都经过编码,QString派生类以自己的方式对其进行解码。

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;
    // ...
};

// ...

每个属性类必须有一个独立的编辑器(GUI窗口小部件) - PropertyEditor抽象类再次)IntegerPropertyEditorBooleanPropertyEditor等。

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
{
   // ...
};

// ...

例如,我有一组不同的属性。我不知道我确切拥有哪些属性,因为它们都是Property类的指针我的任务是为这些属性创建指定的编辑器,因此我需要获取IntegerPropertyEditor属性对象是否为IntegerProperty

for (Property* property : propertySet())
    PropertyEditor* editor = createEditor(property);

我对宏做了一个临时的解决方法:

#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");
}

它看起来不是一个很好的解决方案-如果我添加一种新类型的属性及其编辑器,则也必须更新此代码。链接编辑器类和属性类的最方便,最通用的方法是什么?

ALX23z

您想要的东西需要实现反射,尽管没有宏就可以通过笨拙的方式实现想要的东西。我个人推荐@Chipster的解决方案。

如果您仍然对不需要Property提供其自己的编辑器的方法感兴趣...我编写了一个示例,您可以查看一下。

#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;
}

现在,您可以添加额外的课程DEF...你只需要保持引用类EditorT<D>EditorT<E>EditorT<F>...

复杂吧?好吧... C ++中用于此类编程的当前功能是有限的。它正在工作,将来会可用(请参阅Reflection TS),但现在不可用。同样,使用C ++ 20的所有扩展也将更容易实现constexpr

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在Python中将两个类相互链接的正确方法是什么

此代码中的两个类指的是什么?

无需额外配置即可连接来自不同 LAN 的两个实体

将两个独立图与matplotlib结合的最佳方法是什么?

在两个独立的python程序之间传输数据的好方法是什么?

在 HTML 源代码中查找所有空链接(包含 href="x" 的空标签)的最通用方法是什么?

链接两个类

从HTML文件输出两个特定字段的值的最简单方法是什么?

连接两个 JPEG 视频的最简单方法是什么?

查找两个像素之间距离的最简单方法是什么?

检查两个图像是否相同的最简单方法是什么?

在两个工具栏之间拉伸布局的最聪明方法是什么?

检查两个CRgn是否相交的最简单方法是什么?

无需设置即可获得两个列表的差异的更快方法

构建依赖于公共代码的两个 Docker 容器的最佳方法是什么?

在两个相关的类中使用继承的最佳方法是什么

从两个文件路径之一加载数据的最干净,最pythonic的方法是什么?为什么我不能捕获两个相同的异常?

无需PK即可连接两个表

无需复制即可交换两个 SEXP

UML中两个类之间的虚线是什么?

用通用类<T,U>(从C ++到C#的代码端口)的方法比较T的两个变量

对两个完全独立的事物进行grep并将值分配给独立变量的最有效方法是什么?

反编译Scala代码:为什么派生类中有两个重写的方法?

确定两个值是否在一定范围内的最干净,最易读的方法是什么?

比较两个分支的类的最简单方法

Ruby:如何从两个模块类方法重构代码?

为什么使用存储类说明符来确定两个独立的属性?

查找两个项目之间最精确的通用超类

我有两个Xcode项目,找出每个文件中有两个不同的最简单方法是什么?