C++unnamed namespace(匿名命名空间)与static的区别(可用匿名命名空间代替static)

unnamed namespace匿名命名空间

unnamed namespace 是 C++ 中的一种特殊命名空间,它用于封装不希望暴露给外部的实体,例如函数、变量和类等。与普通命名空间不同,unnamed namespace 中定义的实体只在当前文件中可见,不会被其他文件访问到。

unnamed namespace 可以在全局作用域内定义,但不需要使用名称,也不需要在其他地方声明。例如:

namespace {
    
    
    int x; // 只在当前文件中可见
    void foo() {
    
    
        // ...
    }
}

在上面的代码中,x 和 foo() 都被定义在一个匿名的 unnamed namespace 中,它们只在当前文件中可见,其他文件无法访问它们。这种方式可以避免命名冲突和符号重定义等问题,同时也能提高代码的封装性和安全性。

unnamed namespace跟用static在全局作用域定义有什么区别?

// unnamed_namespace_vs_static.cpp

#include <iostream>

namespace {
    
    
    int x; // 在匿名的 unnamed namespace 中定义
    void foo() {
    
    
        std::cout << "In unnamed namespace: x = " << x << std::endl;
    }
}

static int y; // 在全局作用域中使用 static 关键字定义
static void bar() {
    
    
    std::cout << "In static function: y = " << y << std::endl;
}

int main() {
    
    
    x = 10;
    y = 20;
    foo();
    bar();
    return 0;
}

在上面的代码中,x 和 foo() 被定义在一个匿名的 unnamed namespace 中,y 和 bar() 被使用 static 关键字在全局作用域中定义。它们的区别在于:

  • unnamed namespace 中定义的实体只在当前文件中可见,不会被其他文件访问到,而使用 static 定义的实体也只在当前文件中可见,但是它们需要在其他文件中声明如extern才能被访问(不是static定义的实体其他文件也要extern才能访问)。
  • unnamed namespace 中定义的实体可以避免命名冲突和符号重定义等问题,而使用 static 定义的实体也可以解决这些问题,但是需要手动管理符号重定义的问题。
  • unnamed namespace 中定义的实体可以被其他 unnamed namespace 中的实体访问(别误会,还是同一个文件内),而使用 static 定义的实体只能在当前文件中访问。

在上面的示例代码中,foo() 可以访问 x,bar() 可以访问 y,它们都在各自的作用域中可见。如果我们在另外一个文件中定义同名的变量或函数,使用 unnamed namespace 和 static 的方式都可以避免命名冲突的问题。

unnamed namespace 中定义的实体可以被其他 unnamed namespace 中的实体访问(同一个文件内)

// file.cpp

#include <iostream>

namespace {
    
    
    int x = 10;
}

namespace {
    
    
    void foo() {
    
    
        std::cout << "x = " << x << std::endl; // 可以访问前面的 x
    }
}

int main() {
    
    
    foo();
    return 0;
}

使用不同namespace访问来自不同文件的同名变量

// file A.cpp
namespace ns_A {
    
    
int a = 1;
}
// file B.cpp
namespace ns_B {
    
    
int a = 2;
}
// file C.cpp
#include <iostream>

namespace ns_A {
    
    
extern int a;
}

namespace ns_B {
    
    
extern int a;
}

int main() {
    
    
std::cout << "ns_A::a = " << ns_A::a << std::endl; // 输出 ns_A::a = 1
std::cout << "ns_B::a = " << ns_B::a << std::endl; // 输出 ns_B::a = 2
return 0;
}

在这个示例代码中,我们在文件 A 和文件 B 中分别定义了同名的全局变量 a,但它们在不同的命名空间中。在文件 C 中,我们分别使用 namespace ns_A 和 namespace ns_B 声明了两个不同的命名空间,并使用 extern int a 分别引用了两个命名空间中的 a 变量。最后在 main 函数中,我们输出了 ns_A::ans_B::a 的值,这里输出的分别是 1 和 2。

20230403 namespace中的变量定义与声明

源文件:

(example.cpp)

#include "example.h"

namespace kyai
{
    
    
    namespace cw_client_
    {
    
    
        const std::vector<ky_ai_algorithm_info> *m_algo_info_ptr = nullptr;
    }
}

头文件:

(example.h)

namespace kyai
{
    
    
	namespace cw_client_
   	{
    
    
        extern const std::vector<ky_ai_algorithm_info> *m_algo_info_ptr;
	}
}

原则就是,头文件中声明,源文件中定义,加extern能防止重复定义

猜你喜欢

转载自blog.csdn.net/Dontla/article/details/129827976
今日推荐