• using namespace std的若干问题


    平时经常用到using namespace std;但是却不大了解其中的原理,在网上整理了一些相关信息,虽然不是很全面和深入,但是可以

    做一个大致的参考。

    using

    1.在当前文件中引入命名空间

    这是我们最熟悉的用法,例如:using namespace std;

    2.在子类中使用 using 声明引入基类成员名称(参见C++ primer)

    在private或者protected继承时,基类成员的访问级别在派生类中更受限:

    按 Ctrl+C 复制代码

    在这一继承层次中,成员函数 size 在 Base 中为 public,但在 Derived 中为 private。为了使 size 在 Derived 中成为 public,可以在 Derived 的 public
    部分增加一个 using 声明。如下这样改变 Derived 的定义,可以使 size 成员能够被用户访问,并使 n 能够被 Derived 的派生类访问:

    按 Ctrl+C 复制代码

    另外,当子类中的成员函数和基类同名时,子类中重定义的成员函数将隐藏基类中的版本,即使函数原型不同也是如此。如果基类中成员函数有多个重载版本,派生类可以重定义所继承的 0 个或多个版本,但是通过派生类型只能访问派生类中重定义的那些版本,所以如果派生类想通过自身类型使用所有的重载版本,则派生类必须要么重定义所有重载版本,要么一个也不重定义。有时类需要仅仅重定义一个重载集中某些版本的行为,并且想要继承其他版本的含义,在这种情况下,为了重定义需要特化的某个版本而不得不重定义每一个基类版本,可能会令人厌烦。可以在派生类中为重载成员名称提供 using 声明(为基类成员函数名称而作的 using 声明将该函数的所有重载实例加到派生类的作用域),使派生类不用重定义所继承的每一个基类版本。一个 using 声明只能指定一个名字,不能指定形参表,使用using声明将名字加入作用域之后,派生类只需要重定义本类型确实必须定义的那些函数,对其他版本可以使用继承的定义。

    下面是代码示例:

    #include <iostream>
    using namespace std;

    class Base
    {
    public:
    int menfcn(){cout<<"Base function"<<endl; return 0;}
    };
    class Derived : Base
    {
    public:
    using Base::menfcn;//using声明只能指定一个名字,不能带形参表
    int menfcn(int);
    };

    int main()
    {
    Base b; Derived d;
    b.menfcn();
    d.menfcn();//如果去掉Derived类中的using声明,会出现错误:error C2660: 'Derived::menfcn' : function does not take 0 arguments
    std::cin.ignore(std::cin.gcount()+1);//清空缓冲区
    std::cin.get();//暂停程序执行
    }

    namespace

    1.命名空间英语Namespace)表示标识符(identifier)的上下文(context)。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

    例如,设Bill是X公司的员工,工号为123,而John是Y公司的员工,工号也是123。由于两人在不同的公司工作,可以使用相同的工号来标识而不会造成混乱,这里每个公司就表示一个独立的命名空间。如果两人在同一家公司工作,其工号就不能相同了,否则在支付工资时便会发生混乱。

    这一特点是使用命名空间的主要理由。在大型的计算机程序文档中,往往会出现数百或数千个标识符。命名空间(或类似的方法,见“命名空间的模拟”一节)提供一隐藏区域标识符的机制。通过将逻辑上相关的标识符组织成相应的命名空间,可使整个系统更加模块化

    编程语言中,命名空间是一种特殊的作用域,它包含了处于该作用域内的标识符,且本身也用一个标识符来表示,这样便将一系列在逻辑上相关的标识符用一个标识符组织了起来。许多现代编程语言都支持命名空间。在一些编程语言(例如C++Python)中,命名空间本身的标识符也属于一个外层的命名空间,也即命名空间可以嵌套,构成一个命名空间,树根则是无名的全局名空间

    函数的作用域可被视作隐式命名空间,它们和可见性、可访问性和对象生命周期不可分割的联系在一起。

    C++语言中,命名空间使用namespace来声明,并使用{ }来界定命名空间的作用域.

    namespace foo {
      int bar;
    }
    
    2.命名空间是类的逻辑分组,它组织成一个层次结构——逻辑树。这个树的根是System。
    名字空间是为了防止名字污染在标准   C++   中引入的。
    它可以将其中定义的名字隐藏起来,不同的名字空间中可以有相同的名字而互不干扰,使用时用域操作符(::)来引用。
    namespace   名字
    {
          定义的数据;
          定义的函数;
          也可以是定义的类。。。。。。


    }

    在应用的时候   使用这些数据和函数名称太麻烦
    给定义在同一德的名字空间内
    不用繁琐的去重新书写和定义
    用名字空间就可以了
    我觉得有点像类     又有点像   头文件   

    使用方法有以下三种:
    1>   using   namespace   sdm;
    然后你就可以使用变量temp:
    temp=9;
    还可以使用sdm中的其他每一个成员。
    2> using   sdm::temp;
    在这个文件中只能使用sdm中的temp这个变量。
    3> 你在使用时直接使用sdm::temp:
    cout < <sdm::temp < <endl;
    使用其它的成员也这样调用。
     
    3.对于一个存在着标准输入输出的C++控制台程序,一般会在#include <iostream>的下一行发现一句话,using namespace std。这句话其实就表示了所有的标准库函数都在标准命名空间std中进行了定义。其作用就在于避免发生重命名的问题。
      1. 关于namespace
      C++引入了命名空间namespace主要解决了多个程序员在编写同一个项目中可能出现的函数等重名的现象。解决方法就是加上自己的命名空间。比如下面的例子:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <iostream>
    using namespace std;
      
    namespace ZhangSan 
    {
        int a=10; //张三把10赋值给了变量a
    }
    namespace LiSi
    {
        int a=5; //李四把10赋值给了变量a
    }
      
    void main()
    {
        int a=1;
        cout<<"张三定义的a="<<ZhangSan::a<<endl;
        cout<<"李四定义的a="<<LiSi::a<<endl;
        cout<<"主函数定义的a="<<a<<endl;    
    }
      上例中的“ZhangSan::a”和“LiSi::a”分别表示了调用张三命名空间中的a变量和李四命名空间中的a变量。这样的好处显而易见,那就是虽然张三和李四这两个程序员都定义了一个变量a,但是并不会出现重名的危险。
    运行结果为:
     
      
      2. 关于using namespace *
      顾名思义,using namespace * 就表示释放命名空间* 中间的东西。好处在于我们在程序里面就不用在每个函数的头上都加上*::来调用。比如说如果上面那个程序,如果我们不在using namespace std,那么我们就需要在主函数中的标准输出流cout函数前面加上std,写成
     
    std::cout
    表示调用std空间里面的标准输出流cout。但是有些时候我们也不能图这个方便,比如说如果在主函数中将命名空间ZhangSan和LiSi的中所定义的变量释放出来,如下例1:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <iostream>
    using namespace std;
      
    namespace ZhangSan 
    {
        int a=10; //张三把10赋值给了变量a
    }
    namespace LiSi
    {
        int a=5; //李四把10赋值给了变量a
    }
      
    void main()
    {
        int a=1;
        using namespace ZhangSan;
        using namespace LiSi;
        cout<<a<<endl;
    }
    这个程序输出结果为:
    如果我们在主函数中把 int a=1给删除,如下例2:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>
    using namespace std;
      
    namespace ZhangSan 
    {
        int a=10; //张三把10赋值给了变量a
    }
    namespace LiSi
    {
        int a=5; //李四把10赋值给了变量a
    }
      
    void main()
    {
        using namespace ZhangSan;
        using namespace LiSi;
        cout<<a<<endl;
    }
    会发现根本就不会通过编译,输出的错误信息为:
    error C2872: “a”: 不明确的符号
      分析可以看出,上面这个例2会引起歧义。因为ZhangSan中间的a被释放出来,同理LiSi中间的a也被释放出来了。那么编译器就不知道到底哪个才是需要输出的a,自然就会引起歧义了。同理,在例1中,编译器同样不知道到底哪个才是需要输出的a,于是它只采用了主函数中自己定义的a,这样程序也不会报错,但是只会输出1,自然结果就如上面的图所示了。
    std
    std是一个类(输入输出标准),它包括了cin成员和cout成员,using name space std ;以后才能使用它的成员。
    #include<iostream.h>中不存在类std,但是他又cin,out的相关函数,不需要使用命名空间了。而第二种标准#include<iostream>,
    它包含了一个类,在类的使用之前要预处理一下,using namespace std;就是这个功能,然后你就可以使用cin,cout这两个成员函数了,
    假设你不使用预处理(using namespace std;),麻烦加上std::cin或者std::cout再去使用它的成员函数(头文件中存在这个类)
     
  • 相关阅读:
    C++学习 之 继承(笔记)
    C++学习 之 类中的特殊函数和this指针(笔记)
    C++学习 之 类的声明及成员的访问(笔记)
    C++学习 之 指针及动态内存分配(笔记)
    C++学习 之 函数的重载及内联(笔记)
    C++学习 之 控制程序流程 (笔记)
    pkg-config too old的解决方法
    编译中出现的undefined reference to XXX
    sourceInsight下标题栏显示文件完整路径
    linux下 sleep() 与 usleep()
  • 原文地址:https://www.cnblogs.com/langzi93/p/2433963.html
Copyright © 2020-2023  润新知