Tutorial Study Image

C++ 命名空间


2023 年 6 月 13 日, Learn eTutorial
718

C++ 中增加了命名空间,因为 C 中不存在命名空间。在 C++ 中,命名空间为同名标识符(如变量、函数和类)提供了作用域。命名空间作用域内的标识符只能通过使用每个标识符的完全限定名称才能在作用域外访问。命名空间是 C++ 的基本组成部分,因为它们有助于我们防止程序内部的命名冲突。如果使用命名空间,多个标识符可以共享相同的名称,只要它们在不同的命名空间中声明即可。

在本教程中,我们将介绍什么是命名空间、如何在 C++ 中创建命名空间、其优点和缺点以及如何使用命名空间。

什么是命名空间?

让我们想象一个教室里有两个同名的学生。我们必须通过他们的姓和名来称呼这两个学生,以便区分他们。这种情景也可能发生在 C++ 中。我们编写的名为 sqrt() 的函数可能已经存在于 C++ 的 cmath 包中。在这种情况下,编译器无法区分这两个函数名。因此,它会产生一个错误。命名空间就是为了防止这种复杂情况而使用的。

命名空间提供了一种方法来避免项目中的名称冲突。在 C++ 中,命名空间用于区分两个或多个同名的变量、方法或类。

创建命名空间

在 C++ 中,创建命名空间与创建/定义类非常相似。在 C++ 中,命名空间通过使用关键字 namespace 定义,后跟命名空间的名称。


namespace MyNamespace
{
    // function, class, and variable declarations
}
 

我们可以在命名空间的作用域内声明用户定义的数据类型(例如类)和嵌套命名空间。

不需要一次性声明所有命名空间成员。命名空间可以分成几个部分,然后可以根据每个部分的作用域定义各种标识符。每个单独定义的部分共同构成一个命名空间。“不连续命名空间”是指在多个部分中声明的命名空间。我们可以这样做是因为 C++ 中的命名空间可以分为多个部分。在本文的后面,我们将讨论不连续命名空间。

命名空间声明特性

在 C++ 中使用命名空间之前,必须遵循以下准则:

  • 命名空间必须在全局作用域或嵌套命名空间中声明。
  • 对于我们的命名空间名称,我们可以使用别名(替代名称)。
  • 命名空间可能没有名称。未命名命名空间的成员被视为父命名空间的一部分。
  • 命名空间定义可以应用于多个文件。它们不会被修改或替换。
  • 命名空间声明中不存在 public 和 private 访问说明符。

如何在 C++ 中使用命名空间?

在 C++ 中,有三种使用命名空间的方式:

  • 使用作用域解析运算符
  • 使用声明
  • 使用声明(局部导入)
  1. 使用作用域解析运算符 (::)

    要调用/访问在命名空间内声明的任何成员(变量、方法或类),请使用作用域解析运算符 (::) 和命名空间的名称。

     

    
    #include <iostream>
    using namespace std;
    
    namespace learnEtutorials1
    {
        void greet() 
        { 
            cout << "Hello from namespace learnEtutorials1." << endl; 
        }
    }
    
    namespace learnEtutorials2
    {
        void greet()
        {
            cout << "Hello from namespace learnEtutorials2." << endl;
        }
        
        int var = 20;
        
        int func()
        {
            return var * 2;
        }
    }
    
    int main()
    {
     // Run the greet() function present in learnEtutorials1
     learnEtutorials1::greet();  // used scope resolution operator in order to call this function
    
     // Run the greet() function present in learnEtutorials2
     learnEtutorials2::greet();
     
     return 0;
    }
    
     
    

    输出

    
    Hello from namespace learnEtutorials1.
    Hello from namespace learnEtutorials2.
    

    在上述示例中,定义了两个命名空间——learnEtutorials1 和 learnEtutorials2。这两个命名空间都包含相同的函数 greet()。在主程序中,这两个函数都使用作用域解析运算符和相应命名空间的名称来调用。因此,我们能够避免任何可能导致错误的冲突。

  2. 使用声明

    借助 using 指令,我们可以将另一个程序文件中的完整命名空间导入到我们的程序文件中。导入命名空间的作用域将是全局的。此指令还可以用于将命名空间导入到另一个命名空间或甚至另一个程序中。

    使用指令的语法。

    
    using namespace namespace_name;
     
    

    例如:假设以下命名空间包含在名为 "namespace_learnEtutorial1.h" 的头文件中

    
    // namespace_learnEtutorial1.h
    namespace School
    {
        int school_capacity = 600;
        
        class Students
        {    
            int no_of_students = 450;
        };
    }
     
    

    让我们将上述文件添加到 main.cpp C++ 程序中

    
    // main.cpp
    
    // including the header file
    #include " namespace_learnEtutorial1.h"
    
    void school()
    {
        using namespace School;  // using directive
        // Now, any variables, functions, or classes found in the School namespace can be utilized directly.
        // creating an object with the class Students Students s1 with the name s1.
    Students S1; 
    }
     
    

    using 指令允许我们在 main.cpp 文件中使用 Students 类,即使它是在 learnEtutorial.h 命名空间文件中创建的。

  3. 使用声明(局部导入)

    与 using 指令相比,using 声明略有不同。我们只在 using 声明中使用作用域解析运算符一次导入一个命名空间成员。只有当前作用域才能访问导入的成员。

    使用声明的语法

    
    using namespace_name::member_name;
     
    

C++ 如何使用命名空间

在 C++ 中,每当我们定义一个命名空间时,我们可以使用命名空间的名称和作用域解析运算符来访问其中声明的任何变量、函数或类。

作用域解析运算符使编译器将程序的控制权切换到命名空间块。即使命名空间没有名称,也可以在块外部访问命名空间块中指定的成员;这无需使用作用域解析运算符即可实现(就像访问全局变量一样)。如果命名空间是嵌套的,我们可以多次使用作用域解析运算符来访问它。

命名空间的优点

  • 易于使用库:命名空间允许我们在一个程序中使用多个库,并使用作用域解析运算符区分变量名。
  • 可重用变量名:在一个 C++ 程序中,我们可以多次使用相同的变量名。
  • 提高代码可读性:通过使用命名空间在多个文件和库中指定相似的代码,可以提高代码可读性。

命名空间的缺点

  • 混淆的函数调用 - 如果函数在多个地方定义,命名空间可能导致它们被模糊地调用。
  • 错误地使用 using 指令可能导致意外的程序行为。

结论

  • 我们可以通过使用命名空间将变量、类、对象以及函数等事物捆绑在一个名称下。
  • 命名空间可以有名称,也可以没有名称。
  • 命名空间可以定义在多个文件和部分中。每个组件共同构成最终的命名空间。
  • 在 C++ 中使用命名空间有三种方式:使用声明、使用指令和作用域解析运算符。