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. 什么时候使用名称空间,以及该怎么使用

在这里插入图片描述

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