c++學習記錄之名稱空間,命名空間

1. 爲什麼會有名稱空間

如果有2個庫,都用了同名的函數,或者有同名的兩個類,所以出現了名稱空間的方式

2. 定義命名空間

命名空間的定義使用關鍵字 namespace,後跟命名空間的名稱,如下所示:

namespace namespace_name {
   // 代碼聲明
}

爲了調用帶有命名空間的函數或變量,需要在前面加上命名空間的名稱,如下所示:

name::code;  // code 可以是變量或函數

3. 一個簡單演示命名空間的例子

test.cpp

#include <iostream>

using namespace std;

namespace first_space {
    void func() {
        cout << "first_space" << endl;
    }
}

namespace second_space {
    void func() {
        cout << "second_space" << endl;
    }
}

int main(int argc, char *argv[]) 
{
    first_space::func();

    second_space::func();
    return 0;
}

程序的運行結果!

lydia@lydia:~/sgy/c++_learn/namespace$ ./test
first_space
second_space

4. using聲明和using編譯指令

您可以使用 using namespace指令,這樣在使用命名空間時就可以不用在前面加上命名空間的名稱。這個指令會告訴編譯器,後續的代碼將使用指定的命名空間中的名稱

using聲明將特定的名稱添加到它所屬的聲明區域中。

using 聲明的樣子

using Jill::fetch;

例如main()中的using 聲明Jill::fetch將fetch加入到mian()定義的聲明區域中

using編譯指令使所有的名稱都可用,它使名稱空間中的所有名稱都可用,而不需要作用域解析運算符

using namespace Jack;

5. using編譯指令和using 聲明的區別

下面這個例子很能說明他們之間的區別

5.1 using編譯指令放在全局聲明區域,編譯能通過,但是訪問同名變量會有歧義,報錯

test.cpp
只是使用using namespace 編譯指令,不使用這個test_var變量的話編譯是能夠通過的!

#include <iostream>

using namespace std;
namespace first_space {
    int test_var = 2;
}

int test_var = 9;
using namespace first_space;
int main(int argc, char *argv[]) 
{
    //cout << "test_var:" << test_var << endl;
    return 0;
}

編譯的結果,並沒有報錯!

lydia@lydia:~/sgy/c++_learn/namespace$ g++ -o test test.cpp
lydia@lydia:~/sgy/c++_learn/namespace$

使用這個變量就會出現歧義,因爲不知道使用的是全局變量test_var,還是namespace first_space 裏的test_var!
test.cpp

#include <iostream>

using namespace std;
namespace first_space {
    int test_var = 2;
}

int test_var = 9;
using namespace first_space;
int main(int argc, char *argv[]) 
{
    cout << "test_var:" << test_var << endl;
    return 0;
}

編譯的執行結果!會出現變量的歧義

lydia@lydia:~/sgy/c++_learn/namespace$ g++ -o test test.cpp
test.cpp: In function ‘int main(int, char**):
test.cpp:12:28: error: reference to ‘test_var’ is ambiguous
     cout << "test_var:" << test_var << endl;
                            ^~~~~~~~
test.cpp:8:5: note: candidates are: int test_var
 int test_var = 9;
     ^~~~~~~~
test.cpp:5:9: note:                 int first_space::test_var
     int test_var = 2;
         ^~~~~~~~

5.2 using編譯指令放在函數內部(如main函數內)聲明區域,編譯能通過,但是訪問同名變量會有歧義,報錯

結果是一樣的!

5.3 using聲明放在全局聲明區域,編譯不能通過!

test.cpp

#include <iostream>

using namespace std;
namespace first_space {
    int test_var = 2;
}

int test_var = 9;
using first_space::test_var;
int main(int argc, char *argv[]) 
{
    
    //cout << "test_var:" << test_var << endl;
    return 0;
}

編譯的結果!

lydia@lydia:~/sgy/c++_learn/namespace$ g++ -o test test.cpp
test.cpp:9:20: error: ‘test_var’ is already declared in this scope
 using first_space::test_var;
                    ^~~~~~~~
lydia@lydia:~/sgy/c++_learn/namespace$

5.4 using聲明放在函數內部聲明區域,編譯能通過,使用的是局部變量!

test.cpp

#include <iostream>

using namespace std;
namespace first_space {
    int test_var = 2;
}

int test_var = 9;

int main(int argc, char *argv[]) 
{
    using first_space::test_var;    
    cout << "test_var:" << test_var << endl;
    return 0;
}

執行的結果

lydia@lydia:~/sgy/c++_learn/namespace$ ./test
test_var:2
lydia@lydia:~/sgy/c++_learn/namespace$
使用的是名稱空間中的變量!

引用全局變量可以使用**::var的方法**
using編譯指令會使名稱空間中所有的名稱可用。但是不會引起報錯,如果名稱空間中有同名的變量。

6. 名稱空間的嵌套和名稱空間的別名

6.1 嵌套名稱空間的格式

namespace elements
{
    namespace fire
    {
        int flame;
    }
    float water;
}

namespace myth
{
    using Jill::fetch;
    using namespace elements;
    using std::cout;
}

假設要訪問fetch,有兩種訪問的方式

  1. myth::fetch;
  2. Jill::fetch;

using namespace myth 相當於導入了名稱空間 myth和elements
相當於
using namespace myth;
using namespace elements;

6.2 名稱空間的別名

image.png

6.3 未命名的名稱空間

未命名的名稱空間可以當做static來使用,看一下面的這個具體的例子。
在這裏插入圖片描述

6.4 具體的一個名稱空間的比較詳細的使用例子

#include <iostream>
#include <string>
// create the pers and debts namespaces
namespace pers
{
    struct Person
    {
        std::string fname;
        std::string lname;
     };
    void getPerson(Person &);
    void showPerson(const Person &);
}

namespace debts
{
    //using namespace std;
    using namespace pers;
    struct Debt
    {
        Person name;
        double amount;
    };

    void getDebt(Debt &);
    void showDebt(const Debt &);
    double sumDebts(const Debt ar[], int n);
}


namespace pers
{
    using std::cout;
    using std::cin;
    void getPerson(Person & rp)
    {
        cout << "Enter first name: ";
        cin >> rp.fname;
        cout << "Enter last name: ";
        cin >> rp.lname;
    }

    void showPerson(const Person & rp)
    {
        std::cout << rp.lname << ", " << rp.fname;
    }
}

namespace debts
{
    void getDebt(Debt & rd)
    {
        getPerson(rd.name);
        std::cout << "Enter debt: ";
        std::cin >> rd.amount;
    }

    void showDebt(const Debt & rd)
    {
        showPerson(rd.name);
        std::cout <<": $" << rd.amount << std::endl;
    }

    double sumDebts(const Debt ar[], int n)
    {
        double total = 0;
        for (int i = 0; i < n; i++)
            total += ar[i].amount;
        return total;
    }
}


void other(void);
void another(void);
int main(void)
{
    using debts::Debt;
	using debts::showDebt;
    Debt golf = { {"Benny", "Goatsniff"}, 120.0 };
    showDebt(golf);
    other();
    another();
	// std::cin.get();
	// std::cin.get();
    return 0;
}

void other(void)
{
    using std::cout;
    using std::endl;
    using namespace debts;
    Person dg = {"Doodles", "Glister"};
    showPerson(dg);
    cout << endl;
    Debt zippy[3];
    int i;

    for (i = 0; i < 1; i++)
        getDebt(zippy[i]);

    for (i = 0; i < 1; i++)
        showDebt(zippy[i]);
    cout << "Total debt: $" << sumDebts(zippy, 3) << endl;

    return;
}

void another(void)
{
    using pers::Person;;

    Person collector = { "Milo", "Rightshift" };
    pers::showPerson(collector);
    std::cout << std::endl;
}

總結:

1.

image.png

2. 多次使用using 編譯指令和 using 聲明不會報錯

3. 什麼時候使用名稱空間,以及該怎麼使用

在這裏插入圖片描述

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