命名空间
前言
在了解“using namespace std; ”究竟何意?之前要先了解namespace
namespace应用环境
在C/C++中,变量、函数和类都是大量存在的,它们的名称都将存在于全局变量中,可能导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
//C语言没办法解决类似的命名冲突问题,所以C++提出了namespace来解读
int main()
{
printf("%d", rand);
return 0;
}
//编译后报错: error c2365: "rand": 重定义:以前的定义是“函数”
namespace定义
在C++中,namespace是一种用于组织代码的机制,它可以帮助避免命名冲突并提供更为清晰的代码结构。namespace定义了一块独立的命名空间,其中可以包含各种程序元素,如类型、函数、变量和类等。在命名空间中的所有元素都通过命名空间的名称进行限定,这样可以避免多个源文件或库中同名元素之间的冲突。
namespace的语法如下:
namespace NamespaceName {
// Namespace body: declarations and definitions
//命名空间主体 :声明 和 定义
}
定义命名空间,需要用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
几种命名方法和代码举例
- 正常命名空间类型:
namespace Fibonacci //此处的Fibonacci为NamespaceName,因人而异
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
- 嵌套空间命名类型:
// test.cpp
namespace N1
{
int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N2
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
- 同一个工程允许存在多个命名空间,编译器最后会合成同一个命名空间
// ps:一个工程中的test.h和上面test.cpp中两个N1会被合并成一个
// test.h
namespace N1
{
int Mul(int left, int right)
{
return left * right;
}
}
命名空间namespace成员的使用
命名空间中成员该如何使用呢?
eg:
namespace Fibonacci
{
// 命名空间中可以定义变量/函数/类型
int a = 0;
int b = 1;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
// 编译报错:error C2065: “a”: 未声明的标识符
printf("%d\n", a);
return 0;
}
命名空间的使用
命名空间的使用有三种方式:
- 加命名空间名称及作用域限定符
int main()
{
printf("%d\n", N::a);
return 0;
}
- 使用using将命名空间中某个成员引入
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
- 使用using namespace 命名空间名称 引入
using namespce N;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
Add(10, 20);
return 0;
}
【C++入门】命名空间:“using namespace std; ”究竟何意? 完
正文开始using namespace std;
using namespace std;
using namespace std;是C++编程中的一个指令,它的作用是将标准库命名空间std中的所有名称导入到当前代码文件的全局作用域中。这样,在编写代码时,就可以直接使用标准库中的类、函数、变量等,而不需要每次都加上std::前缀。这可以简化代码,尤其是在使用标准库中的大量元素时。
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
使用惯例
std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?
1.在日常练习中,建议直接using namespace std即可,这样就很方便。
2.using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式
副作用
然而,过度使用using namespace std;可能会导致命名冲突,尤其是在包含多个库或在大型项目中。为了避免潜在的冲突和提高代码的清晰度,一些开发者建议只在需要时使用特定的名称,例如using std::cout;,或者在整个代码文件中避免使用using namespace,始终使用完整的命名空间限定符std::.
正确示范
#include <iostream>
int main() {
using namespace std;
int a = 10;
int b = 20;
int sum = a + b;
cout << "The sum of " << a << " and " << b << " is " << sum << endl;
return 0;
}
到这里你会发现为什么using namespace std为什么在函数内部?
其实,在C++中,using声明或using指令有时被限制在函数或类的内部使用,而不是放在全局作用域或文件的顶部,主要是为了避免命名冲突和保持代码的清晰度。尤其是using namespace,通常不推荐在全局作用域使用,原因有以下几点:
- 命名冲突:using namespace std;等声明会将std命名空间中的所有标识符(如函数、类、变量等)引入到当前作用域中。在大型项目中,这可能会导致与项目中其他命名空间内的标识符冲突。
- 代码可读性和维护性:当在每个使用地点明确地写出std::前缀时,代码的可读性会更好。这使得其他开发人员能够清楚地看到哪些标识符来自标准库,哪些来自项目本身。
- 避免意外覆盖:标准库中的某些标识符可能与未来标准库版本中的新增标识符或项目中定义的标识符重名,导致意外覆盖。
- 编码规范:许多编码规范和指导原则建议避免在全局作用域中使用using namespace std;,以维护代码的清晰度和避免潜在的问题。
因此,更推荐的做法是在需要使用标准库元素的局部作用域(如函数或类内部)使用using声明,具体指定需要引入的标识符,或者在每次调用时都使用std::前缀。
例如,
只在某个函数中使用using声明:
void myFunction()
{
using std::cout;
using std::endl;
cout << "Hello, World!" << endl;
}
或者
直接使用std::前缀:
void myFunction()
{
std::cout << "Hello, World!" << std::endl;
}
【C++入门】命名空间:“using namespace std; ”究竟何意? 完