目录
C++兼容C语言的大部分语法,为弥补C语言的不足与实现面向对象和泛型出现了C++
回顾经典,对比C语言和C++
#include<stdio.h>
int main()
{
printf("hello,world\n");
}
相同结果我们如何用C++的功能实现呢
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
}
为什么我们要多写一个using namespace std
,这就涉及到我们的第一个知识点:命名空间域
命名空间-namespace
写命名空间的原因:
先看一个例子:
#include<stdio.h>
int rand = 0;//初始化一个全局变量rand
int main()
{
printf("hello,world\n");
printf("%d\n",rand);
return 0;
}
注意,此时编译器正常运行
#include<stdio.h>
#include<stdlib.h>//新增头文件
int rand = 0;//初始化一个全局变量rand
int main()
{
printf("hello,world\n");
printf("%d\n",rand);
return 0;
}
报错情况:新增头文件#include<stdlib.h>
后报错为:rand
重定义;以前的定义是函数
报错原因:命名冲突;与头文件stdlib.h
库中函数冲突
命名冲突常见场景:
1.命名与库函数名冲突
2.所写函数名相互冲突
在c语言中会出现上列情况产生命名冲突,C++为了解决这一问题,设置了命名空间这一规则
命名空间的使用:
命名空间建立:
namespace name //name:命名空间域名字
namespace A//设置一个命名空间(相当于隔离空间)
{
int rand = 0;//依旧是全局变量,只是放入了命名空间域内
}//注意,这里不用加分号,与结构体和类进行区别
int main()
{
printf("helloo world\n");
printf("%d\n",rand);//注意这里的rand不一样,详看下解
return 0;
}
此时不再报错,不产生命名冲突错误
但是,此时rand默认访问的是全局的rand,不是命名空间中的rand
会产生如下报错:
此时printf("%d\n",rand)
中打印的是<stdlib.h>库中的函数,函数名代表函数指针
所以
namespace A
{
int rand = 0;
}
int main()
{
printf("helloo world\n");
printf("%p\n",rand);//用%p,打印函数指针
return 0;
}
如何使用命名空间域中的变量:
域作用限定符:::
#include<stdlib.h>
namespace A
{
int rand = 0;
}
int main()
{
printf("%p\n",rand);
printf("%d\n",A::rand);
return 0;
}
命名空间使用规则:
命名空间可以嵌套使用:
- 注意,使用的时候也要按层级寻找
namespace A
{
int rand = 1;
namespace a
{
int rand =2;
}
}
int main()
{
printf("%d\n",A::rand);
printf("%d\n",A::a::rand);
}
实际应用:
为方便理解,暂时先用C语言的语法来写一个栈,让我们更加了解命名空间域使用中的作用吧
//Stack.h
#pragma once
#include<stdio.h>
namespace A//用同一个命名空间
{
typedef struct Stack//建立一个栈
{
int top;
int* a;
int capacity;
}ST;
void StackInit(ST* ps);
void StackPush(ST* ps, int x);
}
//Stack.cpp
#include"Stack.h"
namespace A//用同一个命名空间
{
void StackInit(ST* ps)//栈的初始化
{
ps->top = 0;
ps->capacity = 0;
ps->a = NULL;
}
void StackPush(ST* ps, int x)
{
//......
}
}
//Text.cpp
#include "Stack.h"
#include<stdio.h>
int main()
{
A::ST s;//声明一个结构体变量,要加上命名空间域访问
A::StackInit(&s);
A::StackInit(&s,1);
A::StackInit(&s,2);
A::StackInit(&s,3);
A::StackInit(&s,4);
return 0;
}
-
注意:两个相同名字的命名空间会默认为同一个命名空间(多个文件或同一个文件也相同)
展开命名空间:
但此时,使用下来会觉得使用命名空间域会过于麻烦,于是展开命名空间即可避免代码的累赘。
using namespace name//默认指定使用此命名空间,展开此命名空间
//Text.cpp
#include "Stack.h"
#include<stdio.h>
using namespace A//展开命名空间A
int main()
{
ST s;//声明一个结构体变量,要加上命名空间域访问
StackInit(&s);
StackInit(&s,1);
StackInit(&s,2);
StackInit(&s,3);
StackInit(&s,4);//可以省略访问前缀
return 0;
}
注意:这里与“头文件的展开”不一样!
-
头文件展开指的是在程序运行预处理阶段,把头文件的代码进行拷贝
-
展开命名空间可以理解为把围起来的围墙拆掉,变量除了在全局中搜索也默认会去到命名空间中去搜索
展开std命名空间:
std
是C++官方库定义的命名空间
#include <iostream>
using namespace std;//把C++官方库的命名空间展开
注意:在日常练习代码中为了方便可以直接展开,但是在做工程项目时,请不要随意展开。
指定展开命名空间域:
#include <iostream>
int main()
{
int a = 10;
int b = 20;
std::cout<<a<<std::endl
std::cout<<b<<std::endl
}
当我们频繁使用C++库中的函数时,每次都指定命名空间非常 不方便,如果使用using namespace std全部展开的话就会不安全
using std::cout;//展开我需要用到的函数
using std::endl;
#include <iostream>
int main()
{
int a = 10;
int b = 20;
cout<<a<<endl
cout<<b<<endl
}
变量搜索顺序:
#include<stdio.h>
using namespace A;
using namespace std;
int main()
{
//....
}
1.全局变量中搜索
2.A空间域中搜索
3.std空间域中搜索
4.都没找到——>报错