目录
C++是在C语言的基础上,容纳进去了面向对象的编程思想,并且增加了许多有用的库,以及编程范式等,所以C++兼容C,也就是我们写C语言的代码在C++编译环境下也依然能够编译通过。
注意:C++兼容C语言,本篇文章在前半部分主要还是用C语言的书写习惯来讲解C++中的命名空间,所以在前半部分使用的都还是#include<stdio.h>。
一、C++关键字
C++关键字一共有63个。
在这里暂时不进行逐一解释,在后期博客会对此进行分析,大家可以先去菜鸟教程中进行了解,链接如下:C++ 的关键字(保留字)完整介绍 | 菜鸟教程 (runoob.com)。
二、命名空间
在一方面来讲C++是在C的基础上的完善,所以C++要去解决C语言中出现的一些问题,首先就是命名冲突的问题。
2.1 C语言中的命名冲突
我们来观察下面的两个代码:
代码一:
#include<stdio.h>
int rand = 0;
int main()
{
printf("%d\n", rand);
return 0;
}

代码二:
#include<stdio.h>
#include<stdlib.h>
int rand = 0;
int main()
{
printf("%d\n", rand);
return 0;
}

对于上述的两个代码,代码一可以正常运行,但是代码二无法正常运行,这是为什么呢?

在上述图片中,我们知道代码二运行不通过的原因是由于rand重定义,我们包含了库中的头文件,即 #include<stdlib.h> ,上述头文件中定义了一个函数rand,包含头文件相当于把头文件中的内容在预编译期间拷贝一份过来,相当于在全局域中,在代码二中我们也定义了一个全局变量rand,也在全局域中,这时就会有命名冲突的问题。
2.2 C++中命名空间
命名冲突有两种:
- 和库冲突。
- 和项目组中的其他人冲突。
我们知道不同的域中可以有同名的变量,C++解决了C语言中命名冲突的问题,C++使用namespace-命名空间(关键字)来解决命名冲突的问题,使用namespace定义一个域,用域进行隔离。
2.2.1 命名空间的定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{} 中即为命名空间的成员。
例如上述的代码二,我们就可以定义一个名字是A的命名空间,rand就在A这个命名空间域了,将rand变量和stdlib.h中的rand函数进行区分。
#include<stdio.h>
#include<stdlib.h>
namespace A
{
int rand = 0;
}
int main()
{
printf("%d\n", rand);
return 0;
}
在上述代码中,相当于将全局变量rand定义到了一个名字是A的域中,而#include<stdlib.h>是将stdlib.h中的内容拷贝到当前文件中,其中的rand函数在全局域中,两个rand命名的函数和变量不是处于同一个域,就解决了命名冲突的问题。
2.2.2 命名空间的特性
1.命名空间中可以定义变量/函数/类型。
namespace A
{
int rand = 0;
int Add(int x, int y)
{
return x + y;
}
struct A
{
int a[5];
char c;
};
}
2.命名空间可以嵌套。
当一个命名空间足够大的时候,命名空间内部的变量或者函数也会有命名冲突的问题,这时候就需要命名空间的嵌套了。
namespace A
{
int rand = 0;
int Add(int x, int y)
{
return x + y;
}
struct A
{
int a[5];
char c;
};
namespace B
{
int a = 0;
char c = 'k';
}
}
3.同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
例如test.h和hll.cpp中都有A这个命名空间,在最后编译运行时,会合成到同一个命名空间中去。
一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
2.2.3 命名空间的使用
#include<stdio.h>
namespace A
{
int a = 3;
}
int main()
{
printf("%d\n", a);
return 0;
}
对于上述的代码,编译会不通过,在main函数中有要去打印变量a,但在搜索时并没有找到变量a 的定义,这是由于在对变量a进行搜索时,我们不会主动地去命名空间域中去搜索。
对于命名空间域中的成员,我们不能直接使用,什么时候才去命名空间域搜索 ?
命名空间中成员该怎么使用呢?
1.指定访问命名空间域。
在这里我们使用 ::(域作用限定符), ::加在变量的前面,表示去::左边的域访问。注意:如果左边的域是空白,就代表是全局域。
#include<stdio.h>
namespace A
{
int a = 3;
}
int a = 5;
int main()
{
printf("%d\n", ::a); //::左边是空白,代表去全局域访问
printf("%d\n", A::a); //::左边的域是A,代表去A这个命名空间域访问
return 0;
}
2.将命名空间全部展开。(使用using namespace 命名空间名称 引入)
#include<stdio.h>
namespace A
{
int a = 3;
}
using namespace A;
int main()
{
printf("%d\n", a);
return 0;
}
使用using namespace A;将命名空间域A展开,但是展开就相当于将A中的内容放在全局中,我们使用命名空间的初衷是为了防止和别人或者和库中的内容有冲突,将自己定义的变量等使用作用域限定起来,使用using namespace A;将其展开,可能又会造成命名冲突的问题,所以我们不推荐使用这个方式,但是在我们平时写代码的过程中,命名冲突可能性小,所以使用这个方式。
3.把命名空间中常用的部分展开。
C++的标准库是使用的std这个命名空间,我们想要使用cout(输出)和endl(换行),可以单独将他们展开。
#include<iostream>
using std::cout;
using std::endl;
int main()
{
cout << "hello" << endl;
}
2.2.4 补充知识
当一个文件中有三个同名的变量,分别在局部域,全局域以及命名空间域,那么他们的访问顺序是怎样的?
#include<stdio.h>
#include<stdlib.h>
int a = 0; //全局域
namespace A
{
int a = 3;
}
int main()
{
int a = 1; //局部域
printf("%d\n", a);
return 0;
}
对于不同的域中的三个同名的变量来说,优先去访问局部变量,然后是全局变量,最后如果展开了命名空间域或者指定访问才会去命名空间域。
2.2.4 C++库的命名空间
C++标准库中的函数或者对象都是在命名空间std中定义的,所以我们要使用标准库中的函数或者对象都要用std来限定。
我们会发现在写C++时,我们在包含头文件时不再加.h了,这是因为C++有了命名空间这个定义之后,就把C++标准库中的函数或者对象都用std这个命名空间包起来了,为了和旧的库进行区分,就定义了新的标准,不再使用.h了。
三、C++中的输入&输出
在这里由于没有类和对象的知识,所以简单的了解一下即可,之后会进行讲解。
cout相当于输出函数,cin相当于输入函数,endl相当于换行,注意cout和cin都可以连续一行插入或输出多个变量,会自动识别类型。
#include<iostream> //C++中标准库,输入输出是由iostream库提供的
using std::cout;
using std::endl;
using std::cin;
int main()
{
int a = 0;
int x = 0;
double d = 0;
cout << "hello" << " " << 'd' << ' ' << 's' << a << endl; //endl相当于换行
cin >> x >> d;
cout << "hello" << " "<< x << " " << d << endl;
return 0;
}
四、缺省参数
C++前期是在解决C语言中出现的问题,所以我们又引出了缺省参数这一概念。
4.1 定义
缺省参数,声明函数的时候可以让 最右边的连续若干个 参数有缺省值,在调用函数的时候,如果不写相应位置的参数,则调用的参数就为缺省值。
例如:
#include<iostream> //C++中标准库,输入输出是由iostream库提供的
using std::cout;
using std::endl;
using std::cin;
void Func(int a = 0) //在形参位置上,给一个缺省值
{
cout << a << endl;
}
int main()
{
Func(); //没有传参时,使用参数的默认值
Func(5); //有传参时,使用指定的实参
return 0;
}
4.2 缺省参数的分类
4.2.1 全缺省参数
全缺省参数,即在声明时,给每一个形参一个缺省值。
#include<iostream> //C++中标准库,输入输出是由iostream库提供的
using std::cout;
using std::endl;
using std::cin;
void Func(int a = 0, int b = 5,int c = 8)
{
cout << "a =" << " " << a << endl;
cout << "b =" << " " << b << endl;
cout << "c =" << " " << c << endl;
}
int main()
{
Func();
Func(5);//将5传给a
Func(5,10); //将5传给a,将10传给b
Func(5,10,6); //将5传给a,将10传给b, 将6传给c
return 0;
}
注意在这里传参的时候,只能从左往右依次传参,不能跳跃传参。
//即不能如下:
Func(5, ,10);
4.2.2 半缺省参数
半缺省,在声明函数时,给部分参数缺省值,但是这部分也有要求。
本文详细介绍了C++中的命名空间,包括其定义、特性、使用方法以及解决命名冲突的作用。接着讨论了函数重载的概念,参数个数、类型和顺序的不同如何构成重载。然后深入讲解了引用,包括定义、特性、作为参数和返回值的使用,以及与指针的区别。此外,还提到了auto关键字的使用和范围for循环的原理。文章最后简要提及了内联函数和指针空值nullptr的用法。
最低0.47元/天 解锁文章
7524

被折叠的 条评论
为什么被折叠?



