一、namespace的定义
二、命名空间可以嵌套定义
三、多文件中可以定义同名namespace,他们会默认合并到一起,就像同一个namespace一样
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中
即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
#include
#include
// 1. 正常的命名空间定义
namespace my_space
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
// 这里默认是访问的是全局的rand函数指针
printf("%p\n", rand);
// 这里指定bit命名空间中的rand
printf("%d\n", my_space::rand);
return 0;
}
注意没有加限定区域的rand访问的是
命名空间可以嵌套定义,当我们进行多人进行同一个项目,代码合并的时候往往会出现名字冲突,这时候可以使用命名空间的嵌套定义,可以解决这个问题。
以张三和李四为例:
//2. 命名空间可以嵌套
namespace together
{
// 张三
namespace z3
{
int rand = 1;
int Add(int left, int right)
{
return left + right;
}
}
// 李四
namespace l4
{
int rand = 2;
int Add(int left, int right)
{
return (left + right)*10;
}
}
}
int main()
{
printf("%d\n", together::z3::rand);
printf("%d\n", together::l4::rand);
printf("%d\n", together::z3::Add(1, 2));
printf("%d\n", together::l4::Add(1, 2));
return 0;
}
如下例:定义栈和队列放在一个单独头文件中,实现功能放在c++文件中。他们可以使用相同的命名空间。
// Stack.h
#pragma once
#include
#include
#include
#include
namespace my_space
{
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* ps, int n);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
STDataType STTop(ST* ps);
int STSize(ST* ps);
bool STEmpty(ST* ps);
}
// Stack.cpp
#include"Stack.h"
namespace my_space
{
void STInit(ST* ps, int n)
{
assert(ps);
ps->a = (STDataType*)malloc(n * sizeof(STDataType));
ps->top = 0;
ps->capacity = n;
}
// 栈顶
void STPush(ST* ps, STDataType x)
{
assert(ps);
// 满了, 扩容
if (ps->top == ps->capacity)
{
printf("扩容\n");
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity
* 2;
STDataType* tmp = (STDataType*)realloc(ps->a,
newcapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//...
}
// Queue.h
#pragma once
#include
#include
#include
namespace my_space
{
typedef int QDataType;
typedef struct QueueNode
{
int val;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
// 入队列
void QueuePush(Queue* pq, QDataType x);
// 出队列
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
}
// Queue.cpp
#include"Queue.h"
namespace my_space
{
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
// ...
}
// test.cpp
#include"Queue.h"
#include"Stack.h"
// 全局定义了一份单独的Stack
typedef struct Stack
{
int a[10];
int top;
}ST;
void STInit(ST* ps){}
void STPush(ST* ps, int x){}
int main()
{
// 调用全局的
ST st1;
STInit(&st1);
STPush(&st1, 1);
STPush(&st1, 2);
printf("%d\n", sizeof(st1));
// 调用bit namespace的
my_space::ST st2;
printf("%d\n", sizeof(st2));
my_space::STInit(&st2);
my_space::STPush(&st2, 1);
my_space::STPush(&st2, 2);
return 0;
}
编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以
下面程序会编译报错。所以我们要使用命名空间中定义的变量/函数,有三种方式:
• 指定命名空间访问,项目中推荐这种方式。
• using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。
• 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
#include
namespace my_space
{
int a = 0;
int b = 1;
}
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 namespce N;
int main()
{
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
以上就是今天要讲的内容,介绍了namespace的定义和使用。