创建多个对象类型的QList

时间:2014-08-18 02:22:20

标签: c++ qt qobject qlist

我需要创建各种类类型的多个实例(classA,classB,classC),然后将它们存储在一个列表中。可以动态创建这些对象,然后将它们添加到单个QList中吗?类似的东西:

QList<QObject> mylist;
mylist.append(classA());
mylist.append(classB());
mylist.append(classC());

这不会编译,因为对象不是QObject类型。我可以static_cast他们到QObject,但我能够typeid.name()来确定他们的原始类型? (以后再把它们扔掉)?

我找到了使用QList的示例here&lt; QVariant&gt;,但编译器抱怨:

  

错误:没有匹配函数来调用&#39; QVariant :: QVariant(classA&amp;)&#39;

代码:

QList<QVariant> mylist;
mylist.append(QVariant(tempObj));

更新

我通过在追加操作期间创建对象来编译它,并使用:: fromValue。

mylist.append(QVariant::fromValue(ClassA(1,2,3)));

不确定这是对的。 1 - 这会导致在append语句中创建对象的内存泄漏/问题吗? 2 - 为什么我需要:: fromValue才能使这个工作? (这只是制作对象的第二个副本吗?)

我在构造函数中放了一个qDebug,我看到我的带有参数的构造函数被调用了两次,然后复制构造函数被调用一次,并且永远不会调用默认的(无参数)构造函数。我不明白......

2 个答案:

答案 0 :(得分:3)

您可以使用可以包含任意数量的不同类型的QVariantQVariant API

要将QVariant与自定义类型一起使用,您需要将其注册到元类型系统:QMetaType这意味着使用Q_DECLARE_METATYPE(MyClass) Q_DECLARE_METATYPE()

QVariant设计用于保存不同类型的对象,并且当程序员想要通过Qt的接口传递用户定义的类型时Qt本身无法知道哪种类型,它用于各种Qt约定程序员想要使用。

要转换回原始类型,请使用QVariant::canConvert()QVariant::value()的组合:

QVariant v;

MyCustomStruct c;
if (v.canConvert<MyCustomStruct>())
    c = v.value<MyCustomStruct>();

v = 7;
int i = v.value<int>();                        // same as v.toInt()
QString s = v.value<QString>();                // same as v.toString(), s is now "7"
MyCustomStruct c2 = v.value<MyCustomStruct>(); // conversion failed, c2 is empty

您的自定义类型必须提供:

  1. 公共默认构造函数,
  2. 公共副本构造函数,
  3. 公共析构者。
  4. 以下Message类是可在QVariant

    中使用的可接受自定义类型的示例
    class Message
    {
     public:
       Message();
       Message(const Message &other);
       ~Message();
    
       Message(const QString &body, const QStringList &headers);
    
       QString body() const;
       QStringList headers() const;
    
     private:
       QString m_body;
       QStringList m_headers;
    };
    

    您还可以声明自己的&#34;元类型包装器&#34;包含类型和类型的描述。最简单的例子:

    template <typename T>
    class AnyType
    {
    public:
      enum THE_TYPE { MT_INT, MT_STRING };
    
      AnyType(T value, THE_TYPE type) : value(value), type(type) { }
      THE_TYPE getType() { return type; }
      T getValue() { return value; }
    
    private:
      T value;
      THE_TYPE type;
    }
    

答案 1 :(得分:1)

  

我可以将它们static_cast到QObject

不,你不能!这是非法的:

QList<QObject> mylist;

QObjects具有身份概念,是不可复制的类型。你必须通过指针来操作它们,这将是一个QObject值列表。

但更一般地说(关于寻求通过转换来解决这种事情)...... QList和其他模板化容器专门为它们参数化的对象类型分配一定量的内存。因此,实施级别的QList<A>每个项目只有足够的存储量来存储sizeof(A),而QList<B>只能保存sizeof(B)的项目。

首先:如果你施放对象而不是施放指针那么你真的会丢失你无法回复的信息......如果你能甚至让编译器让你这样做。其次:你需要小心,即使你有一个插槽,指向一个“惩罚类型”,并由于这样做的各种陷阱再次返回。尽管指向不同类型的指针与指针大小相同,但你必须考虑像Strict Aliasing Requirement这样的东西。

您可以使用@snowandotherjoys建议的QVariant之类的方法解决此问题。如果您想要更“标准”,可以查看boost::variant

但是经常说需要某种类型的运行时键入的情况可能意味着您需要再次看一下设计。如果classA和classB和classC如此不同以至于没有共同的接口,那么将它们放在一个引人注目的单个集合中又是什么呢?对于没有任何共同点的东西,你有什么用呢?虽然这些的案例出现了(并且激发了变体的存在),但退一步询问你是否真的有其中一个案例是很有价值的。