找回密码
 立即注册
收起左侧

【独家连载】Qt入门与提高 KS04-11 编写自己的公共类库

4
回复
6644
查看
[复制链接]
累计签到:41 天
连续签到:1 天
来源: 原创 2018-11-3 12:05:45 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 baizy77 于 2019-7-2 20:35 编辑

版权声明
---------------------------------------------------------------------------------------------------------------------
该文章原创于Qter开源社区(www.qter.org
作者: 女儿叫老白
转载请注明出处!
---------------------------------------------------------------------------------------------------------------------

网页版课程源码 提取码:1uy7
引言
----------------------------------------------------------------------------------------------------------------------
  在前面的章节中,我们介绍了如何开发一个dll模块。在项目或者产品开发过程中,我们经常会开发一些公共的dll模块用来实现一些基础功能,比如路径解析、svg中的颜色值与QColor互相转换等。今天我们为大家简单介绍一下如何开发公共类库。

正文
----------------------------------------------------------------------------------------------------------------------
  开发dll的技术在前面章节已经详细介绍过,因此本节的重点是给大家举例介绍抽取公共类或接口组成公共类库,也算是对dll开发技术的一次练兵。
    本节给出的示例代码中,给出了如下接口:

  1. namespace ns_train {
  2.     // == 颜色相关 =============================================================================
  3.     /**
  4.     * @brief 解析颜色, 将字符串转换为QColor.
  5.              格式:r,g,b[,a], alpha可选
  6.     * @param[in] strColor  待解析的字符串
  7.     * @return 解析所得的颜色
  8.     */
  9.     KS04_11_Export QColor parseColor(const QString& strColor);

  10.     /**
  11.     * @brief 将QColor格式化未字符串,输出的格式:r,g,b,a
  12.     * @param[in] clr  待转换的颜色
  13.     * @return 解析所得的颜色字符串
  14.     */
  15.     KS04_11_Export QString getColorRgbValue(const QColor& clr);

  16.     // == 文件相关 =============================================================================
  17.     /**
  18.     * @brief 获取指定path的字符串, 如果使用环境变量,格式必须为:"$环境变量名/xxx/xxx"
  19.              接口内部负责:
  20.              1. 将"\"转换为"/"
  21.              2. 自动将环境变量替换为实际路径,环境变量使用$XXX的格式,比如, 输入:"$TRAINDEVHOME/src",输出:"d:/xingdianketang/project/gui/src/"

  22.     * @param[in] strPath 指定路径
  23.     * @return 文件名, 全路径
  24.     */
  25.     KS04_11_Export QString getPath(const QString& strPath);

  26.     /**
  27.     * @brief 获取指定path所在的全目录名, 如果使用环境变量,格式必须为:"$环境变量名/xxx/xxx.yy"
  28.              接口内部负责:
  29.              1. 将"\"转换为"/"
  30.              2. 自动将环境变量替换为实际路径,环境变量使用$XXX的格式,比如, 输入:"$TRAINDEVHOME/src/a.txt",输出:"d:/xingdianketang/project/gui/src/"
  31.     * @param[in] strPath 指定路径
  32.     * @return 文件名所在目录
  33.     */
  34. KS04_11_Export QString getDirectory(const QString& strPath);

  35.     /**
  36.     * @brief 获取指定文件名的名称,如果使用环境变量,格式必须为:"$环境变量名/xxx/xxx.yy"
  37.              接口内部负责:
  38.              1. 将"\"转换为"/"
  39.              2. 自动将环境变量替换为实际路径,环境变量使用$XXX的格式,比如, 输入:"$TRAINDEVHOME/src/a.txt",输出:"a.txt"
  40.     * @param[in] strFilePath 指定文件(全路径)
  41.     * @return 文件名(a.txt)
  42.     */
  43.     KS04_11_Export QString getFileName(const QString& strFilePath);

  44.         /**
  45. * @brief 获取指定strDirectory的当前子目录名, 如果使用环境变量,格式必须为:"$环境变量名/xxx/xxx/xxx/"
  46.           接口内部负责:
  47.           1. 将"\"转换为"/"
  48. 2. 自动将环境变量替换为实际路径,环境变量使用$XXX的格式,比如, 输入:"$TRAINDEVHOME/src/exchange",输出:"exchange"
  49.         * @param[in] strDirectory 指定路径
  50.         * @return 当前子目录名
  51.         */
  52.         KS04_11_Export QString getNameOfDirectory(const QString& strDirectory);

  53.     /**
  54.     * @brief 获取指定目录下的所有文件名
  55.     * @param[in] strPath 指定路径,内部会将"\"转换为"/"
  56.     * @param[in] nameFilters 文件名过滤符,比如:"*.h"
  57.     * @param[in] bRecursive true:递归. false:仅根目录
  58.     * @return 文件名列表, 全路径
  59.     */
  60.     KS04_11_Export QStringList getFileList(const QString& strPath, const QStringList& nameFilters, bool bRecursive);
  61.         /**
  62. * @brief 获取指定文件对于指定目录的相对路径, 比如,"d:/temp/file/a.txt",相 对于 "d:/temp/"的相对路径为"/file/a.txt"。
  63.         * @param[in] strFileName 指定文件(带绝对路径)
  64.         * @param[in] strDirectory 指定路径(带绝对路径),可以不带最后的“/”。
  65.         * @return 相对路径
  66.         */
  67.         KS04_11_Export QString getReleativePath(const QString& strFileName, const QString& strDirectory);
  68.         /**
  69.         * @brief 获取指定文件的md5码。
  70.         * @param[in] strFileName 指定文件(带绝对路径)
  71.         * @return md5码
  72.         */
  73.         KS04_11_Export QByteArray getMd5(const QString& strFileName);
  74. }
复制代码
    可以看出,我们给出的示例中,使用了命名空间。我们建议:在提供公共类库时,要使用命名空间,以便解决命名冲突的问题。
在我们的示例程序接口中,有颜色转换的接口、有路径解析的接口、有处理md5码的接口等等。这些都是一些基础的、公共的功能。抽取基础的、公共的功能模块是我们建立公共类库的原则。
我们以下面两个接口为例,给大家做一下介绍:
  1. QString getPath(const QString& strPath);
  2. QStringList getFileList(const QString& strPath, const QStringList& nameFilters, bool bRecursive);
复制代码
我们分别来看一下:
l 示例接口1,getPath ():
  1.     /**
  2.     * @brief 获取指定path的字符串, 如果使用环境变量,格式必须为:"$环境变量名\xxx\xxx"
  3.              接口内部负责:
  4.              1. 将"\"转换为"/"
  5.              2. 自动将环境变量替换为实际路径,环境变量使用$XXX的格式,比如, 输入:"$TRAINDEVHOME/src",输出:"d:/xingdianketang/project/gui/src/"
  6.     * @param[in] strPath 指定路径
  7.     * @return 文件名, 全路径
  8.     */
  9.     KS04_11_Export QString getPath(const QString& strPath);
复制代码
这个接口用来解析指定路径的字符串, 如果使用环境变量,格式必须为:"$环境变量名\xxx\xxx"。接口内部将windows风格的目录分隔符"\"转换为linux风格的"/"。自动将环境变量替换为实际路径,环境变量使用$XXX的格式,比如,
输入:"$TRAINDEVHOME/src",
输出:"d:/xingdianketang/project/gui/src/"
l 调用该接口的示例代码如下:
  1. /**
  2. * @brief 示例1, 介绍QDir的使用
  3. * @return void
  4. */
  5. void example02(void) {
  6.     QString strPath = "$TRAINDEVHOME/src";
  7.     strPath = ns_train::getPath(strPath);
  8.     QDir dir(strPath);
  9.     QString absPath = dir.absolutePath();
  10.     QString cancPath =  dir.canonicalPath();
  11. }
复制代码
请注意上述代码中的dir.absolutePath()和dir.canonicalPath(),请读者实际测试一下,看看有什么不同。
l 示例接口2,getFileList():
  1. /**
  2.     * @brief 获取指定目录下的所有文件名
  3.     * @param[in] strPath 指定路径,内部会将"\"转换为"/"。支持环境变量,比如"$TRAINDEVHOME\temp"
  4.     * @param[in] nameFilters 文件名过滤符,比如:"*.h"
  5.     * @param[in] bRecursive true:递归. false:仅根目录
  6.     * @return 文件名列表, 全路径
  7.     */
  8.     KS04_11_Export QStringList getFileList(const QString& strPath, const QStringList& nameFilters, bool bRecursive);
复制代码
这个接口用来获取指定目录下的所有文件。支持递归。接口内部将windows风格的目录分隔符"\"转换为linux风格的"/"。支持文件名过滤。支持环境变量,比如"$TRAINDEVHOME\temp"。 可以看出,这些接口在设计时对于跨平台特性和易用性都考虑到了。
    调用该接口的示例代码如下:
  1. /**
  2. * @brief example01, 调用dll中的接口
  3. * @return void
  4. */
  5. void example01(void) {
  6.     QString strPath = "d:\\temp_D";
  7.     QStringList strFilters;
  8. strFilters << "*.gdf" << "*.xml";   
  9. QStringList strList = ns_train::getFileList(strPath, strFilters, true);
  10. }
复制代码
请注意文件名过滤字符串的写法:
    strFilters << "*.gdf"<< "*.xml";
上述语句表示搜索所有的"*.gdf"文件和"*.xml"文件。
上面我们简要介绍了公共类库示例代码中的两个例子,其他几个例子的设计原则类似,我们不再展开,大家可以自行查阅附件代码。
结语
----------------------------------------------------------------------------------------------------------------------
  在设计公共类库时,我们需要把握如下的原则:
    1. 公共类库包含的是公用的、基础功能模块。
    2. 要考虑跨平台特性,比如:字节序、大小端、目录分隔符、目录(文件)名大小写等。
    3. 要考虑易用性。设计时要从使用者的角度而非实现的角度思考问题。
    公共类库在项目、产品开发过程中有着非常重要的地位。如果能提供一个非常好用的公共类库,对于软件研发组织来说,不论是提高效率、降低成本、还是提升代码稳定性都能起到非常重要的作用。
----------------------------------------------------------------------------------------------------------------------



回复

使用道具 举报

累计签到:7 天
连续签到:1 天
2018-12-1 09:11:28 显示全部楼层
讲得非常好!尤其是这点:要考虑易用性。设计时要从使用者的角度而非实现的角度思考问题。
回复 支持 反对

使用道具 举报

累计签到:3 天
连续签到:1 天
2018-12-3 18:20:46 显示全部楼层
老大能详细解释一个库吗

点评

这位朋友,网页版源码已可下载,请在课程目录页获取下载地址。  详情 回复 发表于 2019-9-6 14:09
您好,本节的重点是介绍类库的设计原则,源码不作为重点,如果您对源码感兴趣,可以加入视频课程的学习。  详情 回复 发表于 2018-12-4 08:24
回复 支持 反对

使用道具 举报

累计签到:41 天
连续签到:1 天
2018-12-4 08:24:40 显示全部楼层
本帖最后由 baizy77 于 2018-12-4 08:52 编辑
xinjian185 发表于 2018-12-3 18:20
老大能详细解释一个库吗

您好,本节的重点是介绍类库的设计原则,侧重接口设计而非接口实现,因此源码不作为重点,如果您对源码感兴趣,可以关注视频课程。
回复 支持 反对

使用道具 举报

累计签到:41 天
连续签到:1 天
2019-9-6 14:09:48 显示全部楼层
xinjian185 发表于 2018-12-3 18:20
**** 作者被禁止或删除 内容自动屏蔽 ****

这位朋友,网页版源码已可下载,请在课程目录页获取下载地址。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了