4.3 案例7 QString的6個實用案例

本案例對應的源代碼目錄:src/chapter04/ks04_02。

無論是進行項目研發還是產品研發,都不可避免會碰到重名問題:頭文件重名、模塊名重名、類或結構體重名、接口重名、全局變量重名等等。對於頭文件名重名和模塊名重名的情況,軟件開發組織需要制定軟件研發管理規範進行制度上的約束,而且還要建立專門的組織進行落地管理。解決類重名、接口重名、全局變量重名問題的方法也很簡單:使用命名空間進行管理。本節將介紹如何在Qt開發中使用命名空間。

在4.1節介紹了怎樣開發一個DLL,本節在4.1節的基礎上增加命名空間的使用。一般情況下只爲DLL代碼設置命名空間,不爲EXE代碼設置命名空間(當需要把EXE與DLL設置爲同一個命名空間時除外)。對於某一個DLL項目,一般也只設置一個命名空間。那麼,具體該怎樣使用命名空間呢?使用命名空間進行管理一共分爲兩大步:

(1)在DLL中將代碼寫到命名空間中。

(2)在其他代碼中使用命名空間中的類或接口。

下面進行詳細介紹。

1.在DLL中將代碼寫到命名空間中

在DLL中使用命名空間的語法:

namespace 命名空間名稱 {                                                            

   ...

}

將命名空間內的代碼寫在{}內。請注意命名空間不是類定義,所以{}結束後不寫“;”。爲DLL選擇一個命名空間,本案例使用ns_ks04_02。將DLL的h文件和cpp文件的對外引出類寫到命名空間ns_ks04_02中,見代碼清單4-9中標號①處。在命名空間結束時不寫“;”,見標號②處。建議軟件開發組織建立專門的機構併發布“命名空間管理規範”,以便對新增命名空間進行審批、登記。軟件開發組織應該只允許使用批准後的命名空間。

代碼清單4-9

// myclass.h

#pragma once

#include "ks04_02_export.h"

namespace ns_ks04_02 {                                                            

    class KS04_02_Export CPrint {

        ...

    };

    KS04_02_Export int func1();

    KS04_02_Export int func2(int, float);

}                                                                                 

注意:命名空間的保護範圍應該僅僅是需要引出的類或接口,因此需要把#include "xxx.h"語句排除在外。如果是類的前向聲明語句,那麼要區分對待:

  1. 如果不是該DLL中定義的類,需要把它排除在命名空間之外。
  2. 如果是該DLL中定義的類,需要把它包含到命名空間之內。

在DLL的cpp文件中用同樣的方式把代碼寫到命名空間裏,如代碼清單4-10所示。

代碼清單4-10

// myclass.cpp

#include "myclass.h"

...

namespace ns_ks04_02 {

    void CPrint::printOnScreen(const char* szStr)    {

        if (NULL == szStr)

            return;

        cout << szStr << endl;

    }  

    int func1()   {

        return 0;

    }

    ...

}

2.在代碼中使用命名空間中的類或接口

在EXE或其他DLL中使用ks04_02_dll中定義的類或接口時,需要使用命名空間。見代碼清單4-11。在標號①處、標號②處採用了命名空間的語法,即命名空間名稱::類名、命名空間名稱::接口名的寫法。

代碼清單4-11

// main.cpp

...

#include "myclass.h"

int main(int argc, char * argv[]) {

               ...

    ns_ks04_02::CPrint pr;                                                      

    pr.printOnScreen("it is a test!");

    ns_ks04_02::func1();                                                        

    ns_ks04_02::func2(2, 3.f);

    return 0;

}

目前爲止,已在DLL中定義了命名空間並在EXE中使用了DLL中的引出類、引出接口。現在說明幾點注意事項。

1)不在頭文件中使用using namespace xxx這種代碼

在頭文件中使用using namespace xxx的代碼會導致命名空間污染。使用命名空間的示意代碼見代碼清單4-12。

代碼清單4-12

// 推薦的寫法

ns_ks04_02::CPrint  printObject;                                                 

// 不推薦的寫法

using ns_ks04_02::CPrint;                                                        

CPrint printObject;                                                               

推薦使用標號①處的寫法,不推薦標號②處的寫法。採用標號②處的寫法時,標號③處用CPrint定義printObject時就可以不寫“ns_ks04_02::”了。但是,如果在同一個文件中包含的其他頭文件(屬於別的DLL)中也存在另一個叫CPrint(類名相同)的類時,就會有問題了。所以,建議採用ns_ks04_02::CPrint的寫法。

2)當需要爲EXE項目設置命名空間時,不要把main()函數放到命名空間裏

有時候EXE和DLL同屬一個大項目,爲了方便調用DLL中的類,就會把EXE項目的代碼也設置到跟DLL相同的命名空間中。這種情況下應該把main()函數排除在外,否則編譯器會認爲mian()函數屬於命名空間,而不會把它當作正常的main()函數入口(正常的main函數入口應該是全局的),從而導致編譯錯誤。代碼清單4-13是無法編譯通過的,需要把main()函數從命名空間的範圍中排除纔行。

代碼清單4-13

// main.cpp

// 錯誤的代碼

namespace ns_ks04_02 {

    int main(int argc, char* argv[])  {

    }

}

3)用了命名空間也不是一勞永逸

軟件開發組織應制定軟件研發管理制度並且嚴格執行。比如,制定命名空間管理規範,規定對外引出的類或接口必須提供命名空間保護、命名空間的名稱需要提請相關機構審覈等等。在規範的軟件研發活動中,使用命名空間進行管理是最最基礎的工作,因爲這會避免很多不必要的問題。即使認爲目前開發的類不會跟別人重名,也應該從一開始就養成使用命名空間的良好習慣。因爲良好的習慣會潛移默化地影響軟件研發活動,對軟件研發人員的未來之路肯定會產生有益的影響。

----------------------------------------------------------------------------------------------------------------------------------------------

《Qt 5/PyQt 5實戰指南》目錄


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章