zoukankan      html  css  js  c++  java
  • C++ using声明和using指示

    using 声明

    using声明(using declaration),一次引入命名空间的一个成员。通过using声明,我们可以清楚知道程序中使用的到底是哪个名字。using声明不允许同名成员,如果有,就不能使用using声明,可以用全名替代。
    有效范围从using声明处开始,一直到using声明所在的作用域结束为止,超出有效范围就要使用全名,同时外层作用域的同名实体将被隐藏。
    using声明语句可以出现在global作用域、local作用域、namespace作用域以及class作用域。其中,在class作用域,using声明只能指向基类成员(如using Base::size)。

    形式:

    using namespace_name::member_name
    

    例如,如果不使用using声明,声明成员std::cout, std::endl,那么每次访问时,就要带上其命名空间(形如"std::"):

    #include <iostream>
    
    int main()
    {
    	std::cout << "hello, c++" << std::endl; // 没有using声明的成员,需要手动编写完整名字
    	return 0;
    }
    

    如果使用了using声明,那么其作用域内,访问对应成员时,无需"std::":

    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    int main()
    {
    	cout << "hello, c++" << endl; // 已经添加了using声明,作用域内,无需再编写完整名字
    	return 0;
    }
    

    using声明与名称遮掩

    我们知道,在继承体系中,derived class成员如果与base class成员同名,就会存在名称遮掩问题(见Effective C++ 条款33),即通过derived class对象访问成员时,无法访问base的同名(重载)成员函数。而使用using声明,可以消除这个问题。

    存在名称遮掩的示例

    // 存在名称遮掩问题
    class Base {
    public:
    	void mf1();
    	void mf1(int);
    };
    
    class Derived {
    public:
    	void mf1(); // 遮掩Base class的同名函数(包括Base的所有重载函数)
    };
    
    Derived d;
    d.mf1(1); // 错误:由于Base::mf1名称被Derived遮掩,无法访问 void Base::mf1(int)
    

    注:名称遮掩与是否为virtual函数无关。

    使用using声明解决名称遮掩问题:

    // 不存在名称遮掩问题
    class Base {
    public:
    	void mf1();
    	void mf1(int);
    };
    
    class Derived {
    public:
    	using Base::mf1; // Base的mf1在Derived可见,不再被遮掩
    	void mf1();
    };
    
    Derived d;
    d.mf1(1); // OK: 调用Base::mf1(1)
    

    using 指示

    using 指示(using directive)将namespace的所有成员提升到作用域可见。允许定义同名变量,如果要访问global成员,就要使用"::i"这样的符号。

    namespace blip {
    	int i = 16, j = 15, k = 23;
    }
    
    int j = 0;
    int main()
    {
    	// using指示,blip中名字被“添加”到global作用域
    	using namespace blip;
    
    	++i;           // OK: blip::i 设为17
    	++j;           // 二义性错误:是blip::j, 还是global j?
    	++::j;         // OK: global j 设为1
    	++blip::j;     // OK: blip::j设为16
    	int k = 97;    // 当前局部k隐藏blip::k
    	++k;           // OK: local k 设为98
    	return 0;
    }
    

    头文件与using声明或者using指示

    using声明和using指示会将名字注入到所有包含该头文件的文件中,而头文件应该只负责定义接口部分的名字,而不定义实现部分的名字。因此,通常情况下,头文件最多只在函数(local)作用域或namespace内使用using声明或指示。

    注意: 在头文件中,尽量避免using指示,因为using指示会引入指定命名空间内所有成员名字,从而污染所有include该头文件的文件。

  • 相关阅读:
    Hibernate系列教材 (五)- 基础
    Hibernate系列教材 (四)- 基础
    Hibernate系列教材 (三)- 基础
    Hibernate系列教材 (二)- 基础
    Hibernate系列教材 (一)- 基础
    Spring系列教材 (六)- 注解方式测试
    LDU20级新生排位赛第三场
    POJ3678——Katu Puzzle(2-SAT)
    进阶指南图论——闇の連鎖 I. 黑暗的锁链(树上差分+LCA)
    2021年度训练联盟热身训练赛第一场——Early Orders(单调栈)
  • 原文地址:https://www.cnblogs.com/fortunely/p/15658804.html
Copyright © 2011-2022 走看看