聯系我們 - 廣告服務 - 聯系電話:
您的當前位置: > 關注 > > 正文

今日熱搜:如何使用using聲明防止命名沖突?命令空間的using聲明

來源:CSDN 時間:2023-03-02 09:34:42

1、概述

我們用到的庫函數基本上都屬于命名空間std的,在程序使用的過程中要顯示的將這一點標示出來,如std::cout。這個方法比較煩瑣,而我們都知道使用using聲明則更方便更安全。


(資料圖)

這個我們程序員肯定都知道了,今天突發奇想就想對using整理一下。

2、命令空間的using聲明

我們在書寫模塊功能時,為了防止命名沖突會對模塊取命名空間,這樣子在使用時就需要指定是哪個命名空間,使用using聲明,則后面使用就無須前綴了。例如:

using std::cin;//using聲明,當我們使用cin時,從命名空間std中獲取它int main(){int i;cin >> i;//正確:cin和std::cin含義相同cout << i;//錯誤:沒有對應的using聲明,必須使用完整的名字return 0;}

需要注意的是每個名字需要獨立的using聲明。例如:

using std::cin;//必須每一個都有獨立的using聲明using std::cout;  using std::endl;//寫在同一行也需要獨立聲明

位于頭文件的代碼一般來說不應該使用using聲明。因為頭文件的內容會拷貝到所有引用它的文件中去,如果頭文件里有某個using聲明,那么每個使用了該頭文件的文件就都會有這個聲明,有可能產生名字沖突。

3、在子類中引用基類成員

在子類中對基類成員進行聲明,可恢復基類的防控級別。有三點規則:

在基類中的private成員,不能在派生類中任何地方用using聲明。在基類中的protected成員,可以在派生類中任何地方用using聲明。當在public下聲明時,在類定義體外部,可以用派生類對象訪問該成員,但不能用基類對象訪問該成員;當在protected下聲明時,該成員可以被繼續派生下去;當在private下聲明時,對派生類定義體外部來說,該成員是派生類的私有成員。在基類中的public成員,可以在派生類中任何地方用using聲明。具體聲明后的效果同基類中的protected成員。

例如:

class Base {protected:    void test1() { cout << "test1" << endl; }    void test1(int a) {cout << "test2" << endl; }    int value = 55;}; class Derived : Base //使用默認繼承{public:    //using Base::test1;//using只是聲明,不參與形參的指定    //using Base::value;    void test2() { cout << "value is " << value << endl; }};

我們知道class的默認繼承是private,這樣子類中是無法訪問基類成員的,即test2會編譯出錯。但是如果我們把上面注釋的聲明給放開,則沒有問題。

注意:using::test1只是聲明,不需要形參指定,所以test1的兩個重載版本在子類中都可使用。 但是在往下派生,則只能使用無參函數,具體什么原因就不知道了…

4、使用using起別名

相當于傳統的typedef起別名。

typedef std::vectorintvec;using intvec= std::vector;//這兩個寫法是等價的

這個還不是很明顯的優勢,在來看一個列子:

typedef void (*FP) (int, const std::string&);

若不是特別熟悉函數指針與typedef,第一眼還是很難指出FP其實是一個別名,代表著的是一個函數指針,而指向的這個函數返回類型是void,接受參數是int, const std::string&。

using FP = void (*) (int, const std::string&);

這樣就很明顯了,一看FP就是一個別名。using的寫法把別名的名字強制分離到了左邊,而把別名指向的放在了右邊,比較清晰,可讀性比較好。比如:

typedef std::string (* fooMemFnPtr) (const std::string&);    using fooMemFnPtr = std::string (*) (const std::string&);

來看一下模板別名。

templateusing Vec = MyVector; // usageVecvec;

若使用typedef

templatetypedef MyVectorVec; // usageVecvec;

當進行編譯的時候,編譯器會給出error: a typedef cannot be a template的錯誤信息。

那么,如果我們想要用typedef做到這一點,需要進行包裝一層,如:

templatestruct Vec{  typedef MyVectortype;};// usageVec::type vec;

正如你所看到的,這樣是非常不漂亮的。而更糟糕的是,如果你想要把這樣的類型用在模板類或者進行參數傳遞的時候,你需要使用typename強制指定這樣的成員為類型,而不是說這樣的::type是一個靜態成員亦或者其它情況可以滿足這樣的語法,如:

templateclass Widget{  typename Vec::type vec;};

然而,如果是使用using語法的模板別名,你則完全避免了因為::type引起的問題,也就完全不需要typename來指定了。

templateclass Widget{  Vecvec;};

一切都會非常的自然,所以于此,模板起別名時推薦using,而非typedef。

感謝大家,我是假裝很努力的YoungYangD(小羊)。

責任編輯:

標簽:

相關推薦:

精彩放送:

新聞聚焦
Top 岛国精品在线