日志
4.6 案例10 使用QList处理数据集
2020-12-24 14:56
本案例对应的源代码目录:src/chapter04/ks04_06。
本节介绍Qt的数据处理类QList,QList实际内部还是一个指针数组。如果要使用QList,需要包含其头文件<QList>。本案例也设计了三种编程场景对QList的使用进行介绍。 (1)向QList中添加成员并遍历。 (2)向QList中添加自定义类的对象。 (3)向QList中添加自定义类对象的指针。 下面进行详细介绍。 1.向QList中添加成员并遍历 代码清单4-44中介绍了向QList中添加成员并遍历的方法,这里也使用quint16作为成员对象的类型。 代码清单4-44
向QList中添加成员也用到了push_back()。接下来使用几种不同的方法对链表进行遍历。为了方便,把遍历、打印链表的代码封装为几个接口,以便在其他案例中使用,如代码清单4-45所示。在标号①处,因为传入的参数类型是const引用,所以在printByIterator()接口实现代码中的标号②处,需要使用QList<quint16>::const_iterator定义常量迭代器对象iteList来访问链表。为iteList赋值时需要调用lstObj对象的constBegin()接口,在判断链表首尾时使用QList的constBegin()、constEnd()接口。同理,在标号④处的倒序访问接口中,用QList<quint16>::const_reverse_iterator定义迭代器对象,并且在标号⑤处用的是QList的crbegin()、crend()接口获取链表的倒序首尾。 代码清单4-45
2.向QList中添加自定义类的对象 向QList中添加自定义类的对象时使用CMyClass类,方法同QVector用法类似,见代码清单4-46。 代码清单4-46
代码清单4-46中需要注意的是标号①处的lstObj.push_back(myclass1),这句代码要求CMyClass类提供拷贝构造函数。其实如果不写CMyClass类的拷贝构造函数,程序也能构建成功,因为编译器会为CMyClass类提供默认的拷贝构造函数。尝试一下封掉CMyClass的拷贝构造函数,看看是否能将项目构建成功。其实,封掉CMyClass的拷贝构造函数后,push_back()可以成功调用,但是程序却会出现运行时异常。这是为什么呢?因为编译器提供的默认拷贝构造函数仅仅执行按位复制,也就是将对象的成员变量的值一对一复制,而CMyClass类的成员中有指针,如果按位复制那么就不会为指针变量重新申请内存而是将它和被复制对象指向同一块内存。在CMyClass析构时会出现将同一块内存多次delete的问题,导致出现异常。所以,在本案例中应该为类编写显式的拷贝构造函数。 另外,因为在实现查找功能时用到了std::find(),所以仍然需要为CMyClass类重载operator==操作符。尝试封掉类CMyClass的operator==的重载操作符的定义和实现代码,看看会有什么结果。哈哈,编译器会报错。
编译器明确提示需要为CMyClass提供operator==的重载,所以如果要使用std::find(),那么对类的operator==操作符的重载是不可缺少的。 3.向QList中添加自定义类对象的指针 向QList中添加自定义类对象的指针与QVector的案例类似,见代码清单4-47。 代码清单4-47
代码清单4-47中的标号①处,方法2的代码被封掉的原因也是因为防止重复析构。此处给出方法2是为了演示用迭代器的方式遍历列表的成员。 本节介绍了链表类QList的用法,它跟QVector有很多相似的地方。不同之处在于,如果对性能要求更高一些,应考虑QVector。QLinkedList才是Qt真正意义上的链表,QLinkedList实际上跟std::list是一样的,也是双向链表。 ---------------------------------------------------------------------------------------------------------------------------------------------- 《Qt 5/PyQt 5实战指南》目录 |
下一篇: 无
baizy77:您说的对,已更正。
2021-01-05 13:16