C++_02_命名空间和作用域运算符 - 重写版

发布时间 2023-11-05 22:53:00作者: 尘落曦枫

命名空间

在C++中命名空间(namespace)的作用

  命名空间,就是为了解决同一个源代码中相同命名的变量或者函数之间相互冲突的问题,就是要避免这种冲突,让程序代码中可以多次使用同一个标识符而存在的。

  对于一名开发者而言,代码量过于庞大,或多或少会忘记之间之前用过的变量名或函数名,导致再次定义的时候又用了之前用过的变量名或函数。这样毫无疑问会导致变量名和函数名出现重复定义报错的问题

  比如:

int  flag = 1;      //A声明的变量
// ……             //中间间隔若干行代码
bool flag = true;   //B声明的变量
//必然会导致冲突,编译器无法正确识别,导致报错

  这位同学前面使用flag定义为整形数1,用代号A表示,后面又定义为布尔型true,用代号B表示;两者都使用了同一个表述符flag。这样在程序中是不行的,会出现重复定义的错误,无法编译通过。

那么就使用命名空间来解决吧!

  如下:

//定义
namespace A
{   //A的变量声明
    int flag = 1;
}
namespace B
{   //B的变量声明
    bool flag = true;
}

  这样,通过定义两个命名空间A和B后,使用的两个flag虽然依旧是两个相同的标识符,但增加了前缀后,标识符所属的范围和意义也就完全不同相互独立了。

  在使用这两个表述符的时候记得要加前缀(A::)(B::),这表示完全不相关联的两个标识符

//引用
A::flag = 1;        //使用A定义的变量flag
B::flag = true;     //使用B定义的变量flag

在C++中通过using声明使用命名空间(namespace)

  在c++中除了一对一的引用命名空间以外,还可以通过using范围性的引用!

  如下:

//范围性引用命名空间
using A::flag;   //using表示正在使用,强制无主变量名的引用A命名空间内的对应
//----->的变量名或函数名
A::flag = 1;     //使用A定义的变量flag
B::flag = true;  //使用B定义的变量flag
flag = 1;  //没有前缀空间命名标识,默认使用A定义的变量flag

  using 声明不仅仅可以针对命名空间中的一个标识符,也可以用于声明整个命名空间

//定义
namespace A   
{   //A的变量声明
    int flag = 1;
    int mnt = 2;
}
namespace B
{   //B的变量声明
    bool flag = true;
   bool mnt = false;
}

//引用
using namespace A;  //强制引用A中所有相同标识符
A::flag = 1;        //使用A定义的变量flag
B::flag = true;     //使用B定义的变量flag
flag = 1;           //默认使用A定义的变量flag
mnt = 2;            //默认使用A中的变量mnt

 

通常在程序中采用了 using 声明命名空间都具有很强的霸道属性;|
std:using namespace std;  这一语句涵盖了 std 命名空间中的所有标识符,而该命名空间包含 C++ 所有标准库。
有了这一句就可以不需要每次前缀标识而自由使用std默认的所有标准表述符。(常用:cin 、cout 、、、)

 

局部变量和是否指定具体标识符探索
      using可以指明具体的命名空间成员,也可用来指明作用于范围。
      1、当using声明时,定义局部变量,则只可以using指定命名空间声明,不可以指定具体标识符,否则会冲突报错;
      2、当using声明时,不定义局部空间,则可以using指定命名空间或者具体标识符。
总结:using指定具体的标识符定义局部变量,只能两者存在一种,如果输出使用的标识符未标识作用域,则优先获取局部变量的值。
// 命名空间:
//        就是为了解决同一个源代码中相同命名的变量或者函数之间相互冲突的问题,
//        就是要避免这种冲突, 让程序代码中可以多次使用同一个标识符而存在的。

#include<iostream>
using namespace std;

namespace veryLongName
{
    int a = 400;   //全局变量a
    int b = 200;   //全局变量b
}
int main()
{
//方案1:不指定具体标识符,指定命名空间,定义局部变量
    //1-1 局部变量a
    int a = 200; 

    //1-2 使用veryLongName命名空间
    using namespace veryLongName;//对局部变量可容忍

    //注意:使用veryLongName::a指定具体标识符,具体指定,对局部变量0容忍
    //using veryLongName::a;//err

    cout << "a = " << veryLongName::a << endl;  //400
    cout << "a = " << a << endl;                //200
    //1-3 结论:访问的是局部变量中的a = 200,不指定具体成员,局部变量优先


//方案2:指定具体标识符

    //上面是不标识具体标识符,这里是不定了局部变量
    //int b = 300;  //err,会和指定具体命名空间标准符冲突

    //2-1 具体指定具体标识符,不可定义局部变量
    using veryLongName::b;
    cout << "b = " << veryLongName::b << endl;  //200
    cout << "b = " << b << endl;                //200
    //2-2 结论:不能局部,只能是全局

    return 0;
}

 

解答我的小迷糊:

注意:命名空间和类是两个不同的概念

  1、类几乎可以理解为从C语言中过度而来的结构体,只不过结构体内只有变量,而类中不仅仅又成员变量还可以有成员函数;类的后面有分号 ; 

  2、命名空间是为了解决同一表述符多次引用的命名冲突问题,本质上只是区分变量名或函数名,命名空间的大括号后面一般没有分号( ; )

  3、类是为了组建构成新的数据或函数类型并以此作为一个蓝本,目标是数据和函数类型,作用在本质;而命名空间则完全是为了变量名和函数名服务的,作用在表层,两者之间八竿子打不着,但经常有同学会把两者混淆傻傻分不清。

  4、使用命名空间修饰的标识符时候,一定是          空间名:: 变量名(或函数名)
     使用类定义对象时,一定是       类名   对象名
  5、命名空间定义属于全局变量声明,不能在函数内定义命名空间

 

1、命名空间的定义(  不能在 函数内 定义命名空间)
2、使用命名空间的成员  最安全的方式   命名空间名::成员名
3、using namespace 命名空间名;使用整个命名空间  (重要)

using namespace A;

4、单独 使用命名空间中的具体成员:using 命名空间名::成员名;

using A::a;

5、说明一下main中的std

#include <iostream>
 //使用标准的命名空间std
 //std中所有成员名 可以直接使用
 //cout endl cin都是命名空间std的成员
using namespace std;

int main(int argc, char *argv[])
{
     std::cout << "Hello World!" << std::endl;
     cout << "Hello World!" << endl;
     return 0;
}

 

 

作用域运算符

作用域运算符::

1、作用域运算符作用是表明数据的归属性,一般和命名空间搭配使用;
2、当同时定义了全局变量和局部变量,不使用作用域运算符具体指定归属范围,默认局部变量优先级会更高,会获取输出局部变量。全局变量的值对会被覆盖;
3、当同时定义了全局和局部变量后,不加::表示局部,加::表示全局

命名空间 namespace
C语言_static来限制全局变量在本文件中的使用
C++也支持static,还支持无名命名空间 namespace

1、命名空间只能定义在全局,不允许在函数内定义命名空间
2、命名空间之间可以嵌套,扩充定义
3、命名空间可以存放变量和函数,并且函数也允许类内声明,类外定义
4、无名命名空间namespace可以代替static,表示修饰的对应变量和函数不能被外部文件使用
5、命名空间可以取别名:namespace newname = oldname

//::a //对应未被命名空间限制的全局变量 ,a也等同于::a
//a //对应未被命名空间限制的全局变量 或者 局部变量(局部变量不允许使用命名空间限制)
//使用using namespace veryshortName;//定义范围允许局部变量存在,局部变量优先级最高
//使用using veryshortName::a;//不允许局部变量,会冲突
//局部变量优先级最高
//是using具体变量(不允许局部变量) 未标注归属的,按要求来就完了
//usingnamespace(允许局部局部变量) 未标注归属的,优先取局部变量;没有局部变量按要求使用对应空间变量(但要防止二义性冲突,因为a也等同于::a)