0

在我的 C++/QT 应用程序中,我有一个包含数百个变量的结构,如下所示:

struct MyStruct
{
    int a1;
    double a2;
    struct InnerStruct
    {
        int b1;
        bool b2;
        struct InnerInnerStruct
        {
            char c1;
              .
              .
              .
        };
        InnerInnerStruct b3;
          .
          .
          .

    };
    InnerStruct a3;
      .
      .
      .
};

我想要一个每个结构成员变量的地址映射,它有整数作为键类型,所以我可以通过它的键访问它:

MyStruct ms;
theMap[0] = &(ms.a1);
theMap[1] = &(ms.a2);
theMap[2] = &(ms.a3.b1);
theMap[3] = &(ms.a3.b2);
theMap[4] = &(ms.a3.b3.c1);

theMap[3] = true; // MyStruct::InnerStruct::b2 is 'true' now

我应该如何定义 Map 对象?我需要什么样的深奥才能拥有此功能?普通模板?提升东西?一些抵消技巧?QVariant 不知何故?

注意:不幸的是,Qt 的属性系统不是一个选项。


编辑:关于我的请求的奇怪性质:我从某个地方接收数据帧,比如设备。数据的前 4 个字节指定帧的类型。所以每当我收到这些数据时,我必须把它放入 Device 结构的相应成员变量中。由于有数百种不同的数据类型,而且我需要在不止一个地方使用这种匹配,我想摆脱繁重的工作——或者至少做一次——(“if/else”和“switch”声明)。

4

1 回答 1

0

更新:请参阅我对您问题的其他答案。将每个数据框放入树数据模型中自己的元素中会更简洁。这种元素的子元素将是框架中的数据成员。这与您的各种框架具有不同数量的元素的情况相匹配。如果每个框架都有相同数量的元素,那么表格模型会更适合。Qt 的模型视图系统对所有数据使用 QVariants,并提供索引到任意复杂模型的方法,所以为什么要重新发明轮子。

在内部,您仍然可以使用结构来保存数据,但至少您不需要具有固定的全局(外部)结构。在创建原型模型时,可以为每个顶层元素(例如最顶层)分配其数据类型,在内部创建底层数据结构等。

现在回到你原来的方法。

类似 QVariant 的方法将起作用,如果整数键是运行时属性,这大约是使其真正起作用的唯一方法。如果您希望整数键仅在编译时有用,那么整数指定的模板函数/仿函数/类成员当然可以解决问题。

现在该值已分配给一个变体,“变体”必须将分配转发给目标成员。

theMap 可以是您想要的任何容器类型。该功能在“变体”中。我们称它为句柄,因为它本质上是一个变量的句柄。

您可以编写代码以支持转换,例如,让双句柄允许分配整数可能很有用。

不过,让我重复一遍:这是一个真正邪恶的设计,我认为没有必要做任何如此糟糕的事情。这是一种反模式。它尖叫:有人搞砸了。不要这样做。

下面是最简单的实现。

#include <QMap>
#include <QVariant>

class Handle
{
    QVariant::Type type;
    void * address;
public:
    Handle() : type(QVariant::Invalid), address(0) {}
    explicit Handle(int* p) : type(QVariant::Int), address(p) {}
    explicit Handle(bool * p) : type(QVariant::Bool), address(p) {}
    explicit Handle(double* p) : type(QVariant::Double), address(p) {}
    Handle & operator=(int* p) { return *this = Handle(p); }
    Handle & operator=(int v) {
        if (type == QVariant::Int) { *(int*)address = v; }
        else if (type == QVariant::Double) { *(double*)address = v; }
        else Q_ASSERT(type == QVariant::Invalid);
        return *this;
    }
    int toInt() const { Q_ASSERT(type == QVariant::Int); return *(int*)address; }
    Handle & operator=(bool* b) { return *this = Handle(b); }
    Handle & operator=(bool b) {
        Q_ASSERT(type == QVariant::Bool); *(bool*)address = b;
        return *this;
    }
    bool toBool() const { Q_ASSERT(type == QVariant::Bool); return *(bool*)address; }
    Handle & operator=(double* p) { return *this = Handle(p); }
    Handle & operator=(double d) {
        Q_ASSERT(type == QVariant::Double); *(double*)address = d;
        return *this;
    }
    int toDouble() const { Q_ASSERT(type == QVariant::Double); return *(double*)address; }
};

struct MyStruct
{
    int a1;
    double a2;
    struct InnerStruct
    {
        int b1;
        bool b2;
    } b3;
};

int main()
{
    MyStruct s;
    QMap<int, Handle> map;
    map[0] = &s.a1;
    map[1] = &s.a2;
    map[2] = &s.b3.b1;
    map[3] = &s.b3.b2;
    map[0] = 10;
    map[1] = 1.0;
    map[2] = 20;
    map[3] = true;
    return 0;
}
于 2012-06-25T01:53:09.873 回答