前言
这一篇博客主要开始讲的是c++的部分,主要是命名空间,流插入,流提取和缺省参数。以后我们文件的命名就要用这个样子了
这里说明一下,C++j是包含C的,所以在C++中使用C是可以的
1.命名空间
先说一下C语言的一些问题
如上图所示,因为在库里面有rand这个函数,而且编译的时候会展开库,所以会有命名冲突问题,而C++就可以解决这个问题
int a = 0;
int main()
{
int a = 1;
printf("%d", a);
return 0;
}
这个程序打印的结果是1,就说明了,一个没有说明域的参数,是优先访问局部的,再访问全局的,全局和局部是两个不同的域,不同的域是可以定义同一个变量的,只不过优先级高的域决定那些没有说明的变量,同一个域是不能定义同一个变量的,因为会命名冲突,比如第一个例子,库就是全局的,所以会冲突
int a = 0;
int main()
{
int a = 1;
printf("%d\n", a);
printf("%d\n", ::a);
return 0;
}
如果没有说明访问的域,那么访问优先级是先局部,再全局的,变量前面加上::,就是指定要访问全局的
namespace bite
{
int rand = 0;
}
int main()
{
printf("%d", bite::rand);
return 0;
}
看这个,我们使用了关键字namespace,这个关键字就是定义了一个命名空间,又是一个域,用bite::就可以访问这个命名空间里的东西了,而且是直接去这里访问,并不会去局部和全局
namespace bite
{
int a = 0;
}
int main()
{
printf("%d", a);
return 0;
}
看这个我们就知道了,一个没有说明域的变量,会先访问局部,再全局,但最后不会去访问命名空间,这就相当于这个命名空间是封闭的,必须要事先说明才可以访问,用bite::
namespace bite
{
int a = 0;
}
namespace bite
{
int c = 0;
}
int main()
{
printf("%d\n", bite::a);
printf("%d\n", bite::c);
return 0;
}
这里我们可以看到,如果多个命名空间使用了同一个名字,那么这些是不会冲突的,为什么呢,因为它们是会合并的,而且这个合并是适用于多个文件的,如果多个文件使用了同一个名字的命名空间,那么最后include的时候吗,是会合并的
namespace bite
{
int a = 0;
}
namespace bite
{
int c = 0;
int a = 1;
}
int main()
{
printf("%d\n", bite::a);
printf("%d\n", bite::c);
return 0;
}
因为会合并,所以这样就相当于重命名了
namespace bite
{
int a = 0;
int Add(int a, int b)
{
return a + b;
}
struct st
{
int num;
};
}
int main()
{
printf("%d\n", bite::a);
printf("%d\n", bite::Add(1,5));
struct bite::st B;
B.num = 4;
return 0;
}
这里再说明一下,命名空间里面是可以定义函数,结构体的,想定义什么就定义什么
命名空间的函数与普通变量的使用是一样的,就是结构体稍稍不同,要这样使用struct bite::st
namespace bite
{
int a = 0;
int b = 1;
int c = 2;
}
using namespace bite;
int main()
{
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
这里我们在使用一个关键字using,这个操作叫做展开命名空间,但这并不是像头文件那样把代码全部替换,而这个只是说明一下,这个域不用说明也可以访问了,所以定义了一个没有说明的变量,它的访问顺序先局部域,再全局域,最后才是这个展开的命名空间。
namespace bite
{
int a = 0;
int b = 1;
int c = 2;
}
using bite::a;
int main()
{
printf("%d\n", a);
printf("%d\n", a);
printf("%d\n", a);
printf("%d\n", bite::b);
printf("%d\n", bite::c);
return 0;
}
再说一下,这个展开命名空间。可以只展开命名空间里的某个特定的变量
#include"add.h"
int main()
{
struct bite::st s;
add(&s);
bite::sub(9);
return 0;
}
这里还有一个点,就是这里开始使用结构体的时候要用bite::说一下,注意注意,因为add函数的参数带有这个结构体,然后这个结构体已经是在命名空间里的,而且也还说明了要访问,那么add就不用说明了,但是sub函数,的参数与这个已经说明的结构体没有关系,所以还要重新说明一下
最后再交代一下,创建命名空间的时候,头文件,和那个没有主函数的文件里最好还是不要定义一些变量,使用这些文件还是和以前一样就可以了,只不过在最外面包一个命名空间
2.流插入,流提取
#include<iostream>
using namespace std;
在C++中我们就有了一些别的打印和输入函数,类似于printf和scanf的,但是要使用这些函数,就要用一个头文件,那就是#include,这个头文件是包含了<stdio.h>的,但是这个头文件里面的内容用了namespace std包裹着,还要展开才可以使用,要么你就要用一个函数才展开一下,再或者你每个都写上std::这个就太麻烦了。
#include<iostream>
using namespace std;
int main()
{
cout << 1 <<" "<<'1' <<" "<<"123"<<" "<< 1.2435 << '\n' << endl;
cout << 1 <<" "<<'1' <<" "<<"123"<<" "<< 1.2435 << '\n' << endl;
return 0;
}
这个cout函数与printf是一样的效果,在屏幕上打印内容,只不过感觉cout这个函数还要方便点,因为这个打印不用说是什么类型的参数,你怎么输入,参数都给你想好了,还有那个endl也是std命名空间里的,与换行符是一样的效果
#include<iostream>
using namespace std;
int main()
{
int a;
int b;
cin >> a >> b;
cout << a << " " << b << endl;
return 0;
}
cin这个函数是与scanf一样的效果,都是从键盘上读入数据到参数中,只不过这个函数不用写取地址了
3.缺省参数
#include<iostream>
using namespace std;
void add(int a = 1, int b = 2, int c = 3)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
}
int main()
{
add(2, 3, 4);
return 0;
}
所谓缺省参数的话,就是add函数的参数的样子,就是在写形参的时候就给形参赋个值,如果给这个形参传了值,那么这个形参就是那个值,如果没有传值,那么这个形参就是当初我们赋的那个值
#include<iostream>
using namespace std;
void add(int a = 1, int b = 2, int c = 3)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
}
int main()
{
add(2, 3, 4);
add(2, 3);
add(2);
add();
return 0;
}
但这个只能先给左边的赋值,再给右边的赋值,不能这样的
不能这样直接的想给第一和第三赋值,然后跳过第二个
然后参数全为缺省参数,那么就是全缺省,不然就是半缺省
然后缺省参数只能从右边到左边覆盖
你看如果缺省参数在非缺省参数的左边的话,那么最后那个c该是什么值呢,只有缺省参数尽可能的在右边的时候,才不会有问题,总之,每个缺省参数都必须在非缺省参数的右边,记住,缺省参数在最右边就可以了
总结
好了,这篇博客就结束了,主要是给C++开个头