命名空间是什么?是一种将相关功能和数据封装在一起的方式,以避免名称冲突和提高代码的可读性和可维护性。我们知道,一个大型项目的编写,不是由一个人来写的,一般都是几人到几十人共同完成,每个人完成一个模块,最后进行合并。那么这么多人同时进行编写项目,难免会产生命名冲突问题,比如函数同名了或者变量同名了。那么怎么解决这个问题呢?答案就是每个人都给自己创建一个自己的命名空间。
namespace
关键字,后面加一个命名空间的名字,再加一个{}
,{}
中即为命名空间的成员。#include
#include
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
printf("%d\n", rand);
return 0;
}
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”
我们已经知道了命名空间怎么创建了,那么命名空间中的成员该怎么使用呢?如下:
#include
int y = 0;
namespace xp {
int x = 0;
int Add(int a, int b) {
return a + b;
}
typedef struct Stack {
int *data;
int capacity;
int size;
} ST;
}
int main() {
//这里编译报错,找不到ST
ST* st;
//这里编译报错,找不到变量x
printf("%d", x);
printf("%d", y);
return 0;
}
怎么解决创建命名空间后把成员放到里面,但是在外面找不到这个成员的问题?有三种解决方案:
1.使用命名空间名称加作用域限定符::
(两个冒号):
int main() {
xp::ST *st;
printf("%d", xp::x);
printf("%d", y);
return 0;
}
2.打开命名空间,把里面所有的成员放出来:使用using namespace 命名空间名称
:
using namespace xp;
int main(){
ST* st;
printf("%d", x);
printf("%d", y);
return 0;
}
3.只打开里面某个成员的空间,把这个成员放出来,其他的成员还是需要加作用域限定符才能访问:(常用)
using xp::ST;
int main(){
ST* st;
printf("%d", xp::x);
printf("%d", y);
return 0;
}
注意:命名空间的创建可以套娃,并且访问里面的成员也得套娃使用作用域限定符:
#include
int y = 0;
namespace xp {
int x = 0;
namespace zl {
int Add(int a, int b) {
return a + b;
}
namespace xpzl {
typedef struct Stack {
int *data;
int capacity;
int size;
} ST;
}
}
}
int main() {
printf("%d", xp::x);
xp::zl::Add(2, 3);
xp::zl::xpzl::ST *st;
printf("%d", y);
return 0;
}
我们来看一段刚开始学C++的时候的一段代码:
#include
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{
cout<<"Hello world!"<
这里我们看到#include
不再是
了,变成了
了,在C++中,一般输入输出不再采用scanf
和printf
了,而是采用cin
和cout
,其中这个iostream
也就是**io
流**,它包含了cout、cin、endl(类)
,流插入运算符<<
和==流提取运算符==>>
。流插入运算符<<
用来输出,流提取运算符>>
用来输入。(知道有这么个知识就行了,这里后面会讲深一点)
还发现了cout
,cout
是标准输出流,配合流插入运算符<<
一起使用。类似地,cin
是标准输出流,配合流提取运算符>>
一起使用。
endl
就是一个换行符,相当于C语言的"\n"
。
这里使用了using namespace std;
,相当于打开了命名空间std
,其中cout、cin、endl
都是这个命名空间里的成员。所以使用cout、cin、endl
不需要加上作用域限定符。
#include
int main()
{
//这里编译报错,找不到cout和endl
cout<<"Hello world!"<
相对于C语言,C++的输入输出要高级多了,它能自动识别变量的类型!
int main() {
int a;
double b;
char c;
string d;
// 可以自动识别变量的类型
cin >> a;
cin >> b >> c >> d;
cout << a << d << endl;
cout << b << " " << c << endl;
return 0;
}
string
是新的数据类型,相当于C语言的 char [n]
(长度为n的字符数组),后面会讲。printf
,因为C++兼容绝大部分C语言的语法。缺省参数是在声明函数时为其指定一个默认值,以便在调用该函数时无需指定该参数。使用缺省参数的原因是减少函数调用时的参数数量,简化代码,提高可读性和易用性。
void Func(int a = 0) {
cout << a << endl;
}
int main() {
Func(); // 没有传参时,使用参数的默认值
Func(10); // 传参时,使用指定的实参
return 0;
}
全缺省参数:即函数的参数全是有默认值的。
void Func(int a = 10, int b = 20, int c = 30) {
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
半缺省参数:函数的参数不全是有默认值的。但是有规则:规则是调用时只能从最后一个参数开始省略,且缺省值必须是常量,且缺省参数不能在函数声明和定义中同时出现。
可行:
void Func(int a, int b = 20, int c = 30) {
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
不可行:
//a.h
void Func(int a = 10);
// a.cpp
void Func(int a = 20) {}
// 注意:如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。