C++第一个程序“hello world”的语法解析
一、命名空间namespace
1.1namespace的价值
在下面的代码中:
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”
printf("%d\n", rand);
return 0;
}
如果我们在头文件包含<stdlib.h>
头文件,就会出现编译报错,显示rand重定义。这种冲突的原因是我们定义了全局变量rand
,而在函数开始之前,会展开头文件<stdlib.h>
,而在头文件中,rand
是函数。
- C++引⼊
namespace
就是为了更好的解决这样的问题
1.2namespace的定义
(1)定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
namespace mate
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
注:后不需要加分号
(2)namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量,所以下⾯的rand不在冲突了。
#include <stdio.h>
#include <stdlib.h>
namespace mate
{
// 命名空间中可以定义变量/函数/类型
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", mate::rand);
return 0;
}
- 访问时默认访问全局,要访问命名空间要使用
域作用限定符::
如mate::rand
调用函数也同样mate::Add(1, 2)
调用结构体要注意::
要放在中间:struct mate::Node node
(3)C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的⽣命周期,命名空间域和类域不影响变量⽣命周期。
#include<stdio.h>
#include<stdlib.h>
int x = 1;
namespace mate
{
int x = 100;
}
int main()
{
int x = 10;
printf("%d\n", ::x);
printf("%d\n", x);
printf("%d\n", mate::x);
return 0;
}
- 局部有时,默认访问局部,但是不能去访问别的局部域;
- 访问命名空间,加要访问的命名空间
mate::x
- 访问全局时,
::x
(4)namespace只能定义在全局,当然他还可以嵌套定义
namespace mateng
{
namespace pg
{
int rand = 1;
int Add(int left, int right)
{
return left + right;
}
}
namespace hg
{
int rand = 2;
int Add(int left, int right)
{
return (left + right)*10;
}
}
}
(5)项⽬⼯程中多⽂件中定义的同名namespace会认为是⼀个namespace,不会冲突。
(6)C++标准库都放在⼀个叫std(standard)的命名空间中。
1.3命名空间的使用
编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间⾥⾯去查找。
如下的编码则会报错:
#include<stdio.h>
namespace mateng
{
int a = 0;
int b = 1;
}
int main()
{
// 编译报错:error C2065: “a”: 未声明的标识符
printf("%d\n", a);
return 0;
}
如果我们要使⽤命名空间中定义的变量/函数,有三种⽅式:
(1)之前我们已经讲过,可以给定空间名来进行访问(项目中推荐)
:
#include<stdio.h>
namespace mateng
{
int a = 0;
int b = 1;
}
int main()
{
printf("%d\n", mateng::a);
return 0;
}
那如果我们要频繁的访问呢?
(2)using将命名空间中某个成员展开(项⽬中经常访问的不存在冲突的成员推荐这种⽅式)
:
#include<stdio.h>
namespace mateng
{
int a = 0;
int b = 1;
}
using mateng::a;
int main()
{
printf("%d\n", a);
return 0;
}
(3)展开命名空间中全部成员(项⽬不推荐,冲突⻛险很⼤,⽇常⼩练习程序为了⽅便推荐使⽤。)
:
#include<stdio.h>
namespace mateng
{
int a = 0;
int b = 1;
}
using namespace mateng;
int main()
{
printf("%d\n", a);
return 0;
}
- 展开命名空间相当于把域里面的成员暴露到全局
二、C++的输入和输出
解析C++的第一个程序
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
- io流
<iostream>
是 Input Output Stream 的缩写,是标准的输⼊、输出流库,定义了标准的输⼊、输出对象。- std::cin 是 istream 类的对象,它主要⾯向窄字符(narrow characters (of type char))的标准输⼊流。
- std::cout 是 ostream 类的对象,它主要⾯向窄字符的标准输出流。
- std::endl 是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区。
- <<是流插⼊运算符,>>是流提取运算符。(C语⾔还⽤这两个运算符做位运算左移/右移)
- 使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式,C++的输⼊输出可以⾃动识别变量类型。
- cout和cin可以不同的类型混在一起,也可以连续的输入输出。
- cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使⽤⽅式去⽤他们。
- ⼀般⽇常练习中我们可以using namespace std,实际项⽬开发中不建议using namespace std。
int i = 10;
cout << i <<endl;
double d = 1.1;
cout << d <<endl;
cin >> i >> d;
注:要控制小数点后的精度,目前建议用printf
总结
例如:以上就是本文的内容,本文简单介绍了C++中的命名空间namespace的使用方法,以及输入、输出流的概念和用法。关于C++的其余内容后续还会产出,希望我也能坚持创作。