• C++基础——对于C语言缺点的补充(1)


    目录

    1.命名空间:

    1.1 为什么要引入命名空间:

    1.2 命名空间的作用:

    1.3 如何访问命名空间内的变量:

    1.4 命名空间的嵌套:

    1.5 不同文件下同名命名空间的合并:

    1.6 命名空间的展开:

    2. C++中的输入、输出:

    2.1 C++中如何实现输入、输出:

    2.2 通过 来解释命名空间的部分展开:


    本篇文章中,不会直接给出C++的介绍,而是在C语言的基础上,给出C++语言相对于C语言的一些不同:

    1.命名空间:

    1.1 为什么要引入命名空间:

           C++一定程度上修改了C语言某些特性的不足,并且在C语言的基础上补充了一些新的功能,例如本节标题“命名空间”,下面,将通过一段程序来解释命名空间:

    1. #include
    2. int rand = 0;
    3. int main()
    4. {
    5. printf("%d ", rand);
    6. return 0;
    7. }

            对于上面给出的程序中,先建立了一个名为rand全局变量,随后对这个变量进行打印,在这种情况下,程序是可以正常运行的,但是,如果将上述程序改为下图所示:

    1. #include
    2. #include
    3. int rand = 0;
    4. int main()
    5. {
    6. printf("%d ", rand);
    7. return 0;
    8. }

     当执行此程序时会发生错误,具体错误类型如下图所示:

            不难发现,发生错误的原因是因为变量rand重定义。而导致发生这一错误的原因就是因为在本程序中,多包含了一个头文件stdlib。在这个头文件中,已经包含了一个用于生成随机数的函数rand,而在后面人为定义rand函数,便造成了rand重定义,针对这种错误,可以称为命名空间的冲突。

    1.2 命名空间的作用:

           在了解了命名空间冲突这一概念后,会发现,在C语言中,当需要定义的变量数量较多时,容易发生命名空间冲突这样的错误,在C语言中,也并没有提供解决命名空间冲突这一问题的方法。因此,C++针对这一不足,给出了解决方法,即:通过人为定义命名空间,来解决此问题,定义命名空间的具体代码如下:

    1. #include
    2. #include
    3. namespace violent
    4. {
    5. int rand = 0;
    6. }
    7. int main()
    8. {
    9. printf("%d ", rand);
    10. return 0;
    11. }

          上述图片所展示的内容即利用C++关键字namespace来建立了一个名为violent的命名空间。加上命名空间后,程序便可以正常运行:

            运行结果如上图所示,此时的运行结果是一串随机数,这时因为,在加上命名空间violent后,程序所打印的rand并不是命名空间中的rand,而是头文件stdlib中的函数rand,由于函数名在单独打印时相当于指针,所以,打印结果会是随机数,如果将printf函数中的%d改为%p,打印结果便会正常打印这个函数的地址,即:

          通过上面的例子可以推断出,在加入了命名空间后,编译器并不会访问命名空间中的rand,而是访问头文件stdlib函数中的rand,通过这种方式,解决了命名空间冲突的问题。

    1.3 如何访问命名空间内的变量:

           上面的部分提出:编译器并不会直接访问命名空间中的变量。这里便引出一个问题,即:如何访问命名空间里面的变量?

          访问命名空间的方法,需要利用一个操作符——域作用限定符——::

          具体访问方法如下图所示:

    1. #include
    2. #include
    3. namespace violent
    4. {
    5. int rand = 0;
    6. }
    7. int main()
    8. {
    9. printf("%d ", violent::rand);
    10. return 0;
    11. }

        结果如下:

    通过打印结果可以发现,再进行上述的操作后,成功的访问量命名空间内的变量rand

    1.4 命名空间的嵌套:

          如果在一个命名空间中也出现了两个名字相同的变量,即:

    1. namespace violent
    2. {
    3. int rand = 0;
    4. int rand = 1;
    5. }

    可以通过嵌套命名空间来解决此问题,即:

    1. namespace violent
    2. {
    3. int rand = 0;
    4. namespace violent1
    5. {
    6. int rand = 1;
    7. }
    8. }

    针对嵌套命名空间中的变量的访问,可以通过下面的方式实现,即:

    1. int main()
    2. {
    3. printf("%d ", violent::violent1::rand);
    4. return 0;
    5. }

    结果如下:

    1.5 不同文件下同名命名空间的合并:

            在一个工程的不同文件中,相同名字的命名空间是可以合并的,为了方便演示这个效果,下面命名两个命名空间:test.h,test.cpp,两个文件包含的内容如下方所示:

    1. //Test.h文件
    2. namespace violent
    3. {
    4. int ADD(int x, int y);
    5. }
    1. //Test.cpp 文件
    2. namespace violent
    3. {
    4. int ADD(int x, int y)
    5. {
    6. int z = x + y;
    7. return z;
    8. }
    9. }

    利用下面的代码验证,同一工程下,不同文件中的同名命名空间是否会合并:
     

    1. int main()
    2. {
    3. printf("%d ", violent::violent1::rand);
    4. printf("%d ", violent::ADD(3, 7));
    5. return 0;
    6. }

    打印结果如下:

    可以看到,函数可以正常运行,如果同一工程下的不同文件的同名命名空间不能合并,则调用函数会因为函数只有函数声明,没有函数定义导致无法正常运行。因此,函数的正常运行间接证明了同一工程下不同文件的命名空间是可以合并的。 

    1.6 命名空间的展开:

    在上面的内容中,给出了访问命名空间的方法,即利用域作用限定符对命名空间中的内容进行访问。但是,这种访问方式过于复杂。如果想要简化访问命名空间中内容的方式,可以同命名空间的展开,具体代码如下:

    1. #include
    2. #include
    3. #include"Test.h"
    4. namespace violent
    5. {
    6. int rand = 0;
    7. namespace violent1
    8. {
    9. int rand = 1;
    10. }
    11. int max = 5;
    12. }
    13. using namespace violent;
    14. int main()
    15. {
    16. printf("%d ", max);
    17. printf("%d ", ADD(3, 7));
    18. return 0;
    19. }

    运行结果如下:

    通过运行结果可以看出,代码没有使用域作用限定符,同样完成了对命名空间中元素的访问。其中,展开命名空间的代码为:

    using namespace violent;

            虽然命名空间的展开可以达到简化访问命名空间中变量的作用,但是,并不能轻易展开命名空间,例如C++中自带的命名空间std,此命名空间中包含了C++中的众多函数,如果在不确定认为定义的变量是否与std中的函数名是否冲突的情况下,展开命名空间会导致文章开头的问题。

           对于命名空间的展开,在具体的项目工程中,由于大概率会造成重定义,因此不能展开。但是在日常的个人代码测试及练习中,可以展开命名空间。 对于命名空间的展开还有指定展开这一方式。对于此种展开方式,将在下面的部分给出解释

    2. C++中的输入、输出:

    2.1 C++中如何实现输入、输出:

           在C语言中,输入、输出这两个功能的实现是利用scanf,printf函数来实现的,在C++中,除了上面的两种方法,还可以借助IO库进行实现,即iostream。在IO库中,定义了不同的对象来实现输入,输出的功能,例如:cin用于处理输入的情况,cout用于处理输出的情况。例如:利用上面的方式,来打印hello  world,具体代码如下:

    1. #include
    2. int main()
    3. {
    4. std::cout << "hello world";
    5. return 0;
    6. }

    运行结果如下:

    在C语言中,常常使用\setminus n来完成换行,在C++中,换行的方式多种多样,具体方式如下方代码所示:

    1. #include
    2. int main()
    3. {
    4. /*printf("%d ", max);
    5. printf("%d ", ADD(3, 7));*/
    6. std::cout << "hello world\n";
    7. std::cout << "hello world" << "\n";
    8. std::cout << "hello world" << std::endl;
    9. return 0;
    10. }

     运行结果如下:

    对于最后一行中的endl,这是一个特殊值,称之为操纵符 ,在将其写入到后方时,可以达到换行的目的。

    2.2 通过cin cout来解释命名空间的部分展开:

            输入、输出这两个功能在日常的测试中使用频率很高,不采用命名空间展开,在使用时,使用方法较为繁琐,但是展开命名空间并不一定安全,为了解决上面的两个问题,引出在命名空间这一章节中说到,命名空间的展开存在一种部分展开的方式。代码如下:

    1. #include
    2. using std::cout;
    3. using std::endl;
    4. int main()
    5. {
    6. /*printf("%d ", max);
    7. printf("%d ", ADD(3, 7));*/
    8. //std::cout << "hello world\n";
    9. //std::cout << "hello world" << "\n";
    10. //std::cout << "hello world" << std::endl;
    11. cout << "hello world\n";
    12. cout << "hello world" << "\n";
    13. cout << "hello world" << endl;
    14. return 0;
    15. }

    运行结果如下:

    上述代码中,出现了一个操作符,在C语言中,这个操作符称为位操作符,主要用于整型变量的二进制位的操作,在C++,这个操作符称之为流插入操作符,此操作符的左右两边都接收两个操作数,左边是可以看作输出对象,右边可以看作需要输出的值。

    在上述代码中不难发现,进行命名空间的展开时,并没有直接展开std,即没有使用                      using\, \, namespace\, \, std; 这句代码进行展开,而是

    1. using std::cout;
    2. using std::endl;

    此种展开方式就是部分展开,即只展开命名空间中的某个特定的函数,对应上面的代码,只展开了cout\, \, \, endl

    至此,文章给出了C++中如何进行输出,在C++中,进行输入时,需要利用cin以及流提取操作符>"" class="mathcode" src="https://1000bd.com/contentImg/2024/03/24/19dc6612a51c3860.png">,具体代码如下:

    1. int main()
    2. {
    3. int a, b;
    4. cin >> a >> b;
    5. cout << a << endl << b << endl;
    6. return 0;
    7. }

    运行结果如下:

  • 相关阅读:
    vue2和vue3的声明周期
    如何建立团队知识库管理系统,把分散信息有效整理?
    使用 Pyro 和 PyTorch 的贝叶斯神经网络
    JS之手写bind原理
    认识端口号(netstat指令查看网络状态)
    WhatsApp的两个商业模式该如何选择
    金九银十,一个新的王者在8月即将加冕——Treasure project(TPC)重磅来袭,你参与了吗?
    购物中心如何走出营销困境?
    【安装填坑】-import win32api, sys, os ImportError: DLL load failed: 找不到指定的模块。
    MySQL表设计和多表操作
  • 原文地址:https://blog.csdn.net/2301_76836325/article/details/134222684