命名空间的设置:
避免冲突
命名空间:
如果将变量全部定义在全局可能不安全,都可以进行修改。
如果将变量定义在局部,当出了大括号就不能使用。
所以说在定义一个命名空间的时候
定义函数,变量,命名空间,都称为命名空间中的实体
//命名空间的定义方式
namespace hh
{
int val1 = 0;
char val2;
}// end of namespace hh
大括号后面可以加;也可以不加
定义的时候是没有缩进的,可以在最后一行添加注释使得结尾更加清晰
命名空间的使用方式:三种方式
1.作用域限定符
例如使用std命名空间中的cout 使用std::cout
准确但是繁琐
如果命名空间中套命名空间,需要 :: ::
2.using编译指令 using name space
尽量写在局部,既可以在局部(放在{}中)使用保证在用到的时候才能出来
可能会出现的问题是可能会和全局变量名出现冲突,借助于方式一作用域限定符帮助确定
当不清楚命名空间中的具体情况的时候,不要使用using,因为可能出现命名空间中的实体和自定义的变量和函数出现冲突。
3.using声明机制
初学阶段使用using声明机制,需要什么就添加什么,避免出现using冲突,同时避免每次使用加::
using std::cout;
using std::endl;
仍然是建议将using声明语句放在局部作用域中
【注意】即使命名空间中实体与全局位置实体重名,在局部位置也遵循“就近原则”形成屏蔽
#include <head.h>int num = 10;void test0(){//using声明语句using wd::num;using wd::func;//直接写函数名,不加括号//即使全局作用域存在同名的实体//此处也可以形成屏蔽效果//访问到时wd::numcout << "wd::num:" << num << endl;func();
}int main(){test0();
}
对比使用using编译机制如果全局变量和namespace中变量名字相同会出现冲突,但是使用using声明机制在局部使用的时候会对于全局变量形成屏蔽。
命名空间的嵌套使用
//嵌套命名空间设置
namespace wd
{
int num = 100;void func(){cout << "func" << endl;
}namespace cpp
{
int num = 200;void func(){cout << "cpp::func" << endl;
}
}//end of namespace cpp}//end of namespace wd//调用方式
//方式一,使用作用域限定精确访问实体
void test0(){cout << wd::cpp::num << endl;wd::cpp::func();
}//方式二,using编译指令一次性引入cpp的实体
void test1(){using namespace wd::cpp;cout << num << endl;func();
}//方式三,using声明语句
void test2(){using wd::cpp::num;using wd::cpp::func;cout << num << endl;func();
}
【注意】在using编译机制中,指明使用哪一个命名空间的需要具体
匿名命名空间(与有名命名空间合在一起称为有名命名空间)
匿名命名空间和static定义的静态有点像,不会被跨文件使用到
匿名空间中的变量以及函数的使用,直接用就可以不像有名空间三种方式。
【注意】全局变量和匿名空间同名的变量和函数时,也就是冲突的时候,会有问题!!
【注意】如果使用::作用域限定符,也无法访问到匿名空间中重名的实体,只能访问到全局的实体。
跨模块调用
(1)跨模块调用函数和变量
【注意】如果是在一个文件中定义一个static变量或者函数那么也不能通过extern引入
【注意】匿名空间同理,这两类只能从本模块使用,不能跨模块使用
1. 可以定义在头文件中,是现在别的文件,然后在该文件中直接调用就可以
出现的问题就是把头文件中的内容全部引入进来,开销比较大
2. 可以使用extern的方式,
//externA.cc
int num = 100;void print(){
cout << "print()" << endl;
}//externB.cc
extern int num;//外部引入声明
extern void print();
void test0(){
cout << num << endl;
print();
}
告诉编译器我这有一个缺口,可以进行编译,但是谁来编译填补这个缺口,是在链接的时候确定
g++ externA.cc externB.cc
【注意】大型项目使用的方式往往还是头文件的方式实现,小型文件使用extern方式。因为跨模块调用的关系不清晰,容易出错,比如说如果说多个文件都有同一个变量会出现冲突,外部引用时
(2)跨模块调用有名命名空间
【注意】不能直接用extern wd::val直接引用,需要在该文件中依然定义一个同名命名空间,在文件中使用extern int val;
【注意】在不同的文件中多次定义同名命名空间,多次定义都是放在这一个命名空间中。
【注意】不能跨模块调用匿名命名空间
命名空间中的内容可以进行定义或者声明,命名空间中不能使用实体,也不能对于声明的实体赋值。
命名空间的作用:
1.避免冲突的作用
2. 版本控制,一个版本中的代码保存在一个命名空间中另一个命名空间中
3. 声明主权的作用,命名空间名字(很特别的命名方式)注释可以表明是谁的
命名空间的使用方式:
1. 最好放在命名空间中,而不是全局
2. 尽量在局部使用而不是全局
3. 如果非要使用using编译指令,建议放在所有#include预编译指令后
4. 不要在头文件中使用using编译指令,这样,使得可用名称变得模糊,容易出现二义性
【注意】头文件的使用规则include多个头文件,首先放自定义的头文件,再放C的头文件,再放C++的头文件,最后放第三方库的头文件。
const关键字
const修饰内置类型(系统原有的int)
书写方式:const int num = 10; int const num = 10;对于int和double来说效果是一样的。
使用方式:const关键字必须在一开始的时候就进行赋值,也是一个变量
与宏定义的比较:1.宏定义是在预处理的时候进行替换,const是在编译的时候进行处理 2.宏定义不能明确指明类型容易出错
【重点】const修饰指令类型
对于指针而言不同的书写方式会得到不同的效果。
int num1 = 10;
const int * p = &num1;
//可以修改指向不能修改指向的内容num1 = 20;
//这样也是可以的int const * p = &num1;
//这样也是一样的效果
//point to const 就是指针指向一个const类型元素,也就是不能修改元素值
//理解为围着int转不能修改值const int num3 = 1;
const int * p2 = &num3;
//此处设置指针的时候必须要加上constint num2 = 1;
p2 = &num2;
//const 指针也可以修饰非常量类型数据
int num1 = 10;
int * const num = &num1;
//可以通过指针修改指针指向的内容,但是不能修改指向
//称为常量指针 const to point
//可以从右向左看,先看到const再看到*const int num3 = 1;
int * const p2 = &num3;//error
//因为这样定义的时候会理解为可以修改p2指向的内容,但是这个地方在定义num3的时候是不能改变值
//所以这样得话是会报错的
区分:数组指针和指针数组
函数指针和指针函数