C++关键字&&命名空间

近段时间学习了C++的相关内容, C++还是很火的编程语言!下面分享我的学习心得:关于C++关键字和命名空间的认识

1.C++关键字

C++总计63个关键字,C语言32个关键字

asm do if return try continue
auto double inline short typedef for
bool dynamic_cast int signed typeid public
break else long sizeof typename throw
case enum mutable static union wchar_t
catch explicit namespace static_cast unsigned default
char export new struct using friend
class extern operator switch virtual register
const false private template void true
const_cast float protected this volatile while
delete goto reinterpret_cast

2.命名空间

为什么存在

主要是为了为了解决命名冲突

例子:

#include<stdio.h>
#include<stdlib.h>//里面包含rand函数
int rand = 0;//全局变量rand
int main()
{
    printf("rand = %d\n", rand);//编译器不知道打印的是函数的地址(函数名 == 函数的地址)还是全局变量rand的值
    printf("%d\n",rand());//这样没问题,这样相当于是调用rand函数
    return 0;
}

若rand为全局变量则有问题了,因为rand函数和rand变量都是全局变量,编译器不知道哪个是你要打印的是哪个

image-20220407150621806


但是写成这样没问题:

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int rand = 0;//此时的rand变量为局部变量,局部优先,
    printf("rand = %d\n", rand);//0   局部优先,打印的是局部变量rand的值
    return 0;
}0

此时rand为局部变量就没有问题,全局变量和局部变量可以同名,使用时原则为:局部优先(先使用局部变量)

编译器寻找变量的规则是:先在该作用域中寻找该局部变量,找不到再去全局变量中找,如果还是找不到,就会报错


在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的,


  • 使用命名空间后
#include<stdio.h>
#include<stdlib.h>
namespace M_Space//定义一个叫M_Space的命名空间-域
{
    int rand = 0;
}
int a = 10;
int main()
{
    printf("rand = %d\n", rand);
    // :: 域作用限定符
    printf("命名空间的rand = %d\n", M_Space::rand);//表示rand再M_Space这个域中寻找
    M_Space::rand = 10;
    printf("修改值后:命名空间的rand = %d\n", M_Space::rand);

    printf("%d\n" ,  ::a);//10
    //若域作用限定符的坐标是空白,则说明再全局域中寻找
    return 0;
}

image-20220910231910001


命名空间的定义

命名空间是全局的,命名空间里面的成员也是全局的变量

定义命名空间需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{},{}中即为命名空间的成员

  • 例子
namespace MS  //MS是命名空间的名字 - 域
{
    int a = 0;//a是全局变量,放在静态区,是MS命名空间的成员,
}

域中的成员变量是不能在域中赋值的!只能初始化时候赋初始值


命名空间中的内容,既可以定义变量,也可以定义函数,也可以创建类型(结构体,联合体..)

namespace M_Space
{
    int a = 0;
    int Add(int x, int y)
    {
        return x +y ;
    }

     struct Student
    {
         int age;
         char sex[7];
    };
}
  • 命名空间中的结构体使用时的注意事项
namespace M_Space
{
     struct Student
    {
         int age;
         char sex[7];
    };
}

M_Space::struct Student stu;//err

struct M_Space::Student stu;//写法1

M_Space::Student stu;//写法2

  • 命名空间内部的变量可以定义时初始化,但是不可以在命名空间内再次赋值,要再次赋值要在其它函数内赋值
namespace M_Space
{
    int a = 0;//定义时初始化
    int b;//只定义不初始化

    a = 10;//err
    b = 5;//err
}
M_Space::a = 10;//err  在外部赋值也不可以,要在函数内部赋值
void test()
{
    M_Space :: a = 10;//可以
}

image-20220910231857487

原因分析:

命名空间内创建的是全局变量,全局变量要在函数内部赋值,初始化时只能赋初始值

int a = 10;
a = 20;//err
int main()
{
    a = 10;//OK
    return 0;
}

2.命名空间可以嵌套

namespace N1
{
    int a = 2;
    namespace N2
    {
        int b = 3;
    }
}
int main()
{
    N1::a = 2;
    N1::N2::b = 1;
    //同样也是使用::域作用限定符进行逐层访问
    printf("a = %d b = %d\n", N1::a, N1::N2::b);// 2 1 
    return 0;
}

3.同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中,

namespace N1
{
    int a = 0;
    int b = 2;
}
namespace N1
{
    int a = 1;
}
int main()
{
    printf("a  = %d b = %d\n", N1::a, N1::b);
    return 0;
}

image-20220910231839352

相同名称的命名空间,最后会合成同一个命名空间中,所以相同名称的命名空间里面的成员名字不能相同,否则会报错


命名空间不影响变量的属性,它还是全局变量,只是影响了编译器找该变量的规则 命名空间里面可以只放声明(函数声明)


命名空间的使用

方法1:加命名空间名称及作用域限定符 ::

命名空间名称 :: 成员名;

namespace M1
{
    int a = 10;
}
int main()
{
    printf("before:M1::a = %d\n", M1::a);//10
    M1::a = 20;
    printf("after:M1::a = %d\n", M1::a);//20
    return 0;
}

优缺点:

  • 优点:不会造成命名污染 缺点:使用麻烦

方法2:使用using将命名空间中成员引入

using 命名空间名称 :: 要展开的成员;

namespace M1
{
    int a = 10;
    int b = 20;
}
//单独展开M1中的a变量,其它不展开
using  M1::a;

int main()
{
    printf("a = %d\n", a);//10
    printf("b = %d\n", b);//b未被引入,编译器找不到,会报错
    return 0;
}

想要程序没问题:把b也展开

using  M1::a;
using  M1::b;

方法3:使用using namespace命名空间名称引入

using namespace 命名空间名称 ;

这种写法是直接把整个命名空间展开,使用方便,但是命名空间的隔离作用就失效了

namespace M1
{
    int a = 10;
    int b = 20;
}
//把M1这个命名空间展开-展开到全局
using namespace M1;
int main()
{
    printf("a = %d\n", a);//10
    printf("b = %d\n", b);//20
    return 0;
}

namespace N1
{
    int a = 2;
    namespace N2
    {
        int a = 3;
    }
}

using namespace N1;
int a = 0;
int main()
{
    //printf("a = %d ", a);//err,未知要打印的是N1的成员变量a还是外部的全局变量a
    printf("a = %d ", N1::a);//这样使用了域限定符就可以
    return 0;
}

image-20220910231820323

命名空间N1展开之后,N1里面的全局变量a和外部的全局变量a重名了,N1失去了隔离作用


优缺点:

  • 优点: 使用成员方便
  • 缺点:由于是展开到全局,如果全局也有相同名字变量或函数名等,会造成命名污染,编译器报错
#C/C++#
全部评论
感谢楼主的讲解
点赞 回复 分享
发布于 2022-10-23 18:30 陕西
学习C++命名空间
点赞 回复 分享
发布于 2022-10-15 16:17 河南

相关推荐

09-23 17:42
门头沟学院 Java
兄弟们我绷不住了,小米要求10月份参加编程考试,20级以下(王腾好像21),正式和外包都得去,还要部门大排名,一巴掌给我抽象的回到大学
flex*1022:雷:我们想了很久,到底怎么样才能让用户满意,让工程师保持手感,经过长达180天的思考,我连夜睡服高管,决定发起内部考试,以编程为主
投递小米集团等公司10个岗位
点赞 评论 收藏
分享
09-12 11:55
已编辑
湖南工商大学 Java
那一天的Java_J...:这种一堆问题的,别去
点赞 评论 收藏
分享
评论
2
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务