zoukankan      html  css  js  c++  java
  • using namespace的故事

    1、问题起因(使用boost.asio库时为什么如下图所示using后面不接namespace)

      

      图上的using boost::asio::ip::tcp 在using后面没有namespace,这样是正确的。那么如果加上namespace会是什么结果呢?

      

      

      加上之后如上图所示,出错。为什么?在之前我也一直不能明白原因,查了using的用法但也没有弄清楚。

      其实答案很简单:因为boost::asio::ip 是namespace,而tcp不是,他应该是一个类。

     1 namespace boost{
     2     namespace asio{
     3         namespace ip{
     4             class tcp{
     5                 ...
     6             }
     7             ...
     8         }
     9         ....
    10     }
    11     .....
    12 }

      如上面代码所示,我们就可以写using boost::asio::ip::tcp了,这是using了一个命令空间中的tcp类的作用域。

      这个问题算是解决了。

    2、问题又来了(为什么可以如下图使用)

      

       acceptor是一个(类类型)class_type,然后他又在tcp这个作用域下面,而tcp它是一个类,为什么在这个类中还有类型,其实就是boost::asio::ip::tcp::acceptor (本人的知识在这不够用了,感觉卡在这了)

      这个问题的回答是这样的,如下面代码,代码中有类A,类A中有个类型是iterator类型,这是一个typedef,因此当你使用iterator时,就需要加入A::iterator这样,上图tcp就是那个类,acceptor(应该)就是那个typedef,这样就解释清楚了。

     1 class A_iterator ;                                                                   
     2 class A {                                                                            
     3   public:                                                                            
     4     A(){std::cout << " A is start 
    ";}                                              
     5     ~A(){std::cout << "A is finst 
    ";}                                              
     6     typedef A_iterator iterator;                                                     
     7 };                                                                                   
     8 class test ;                                                                         
     9 class A_iterator {                                                                   
    10   public:                                                                            
    11     A_iterator(){std::cout << "A_iterator is start 
    ";}                             
    12     ~A_iterator(){std::cout << "A_iterator is finsh 
    ";}                            
    13     typedef test test_type ;                                                         
    14 };
      iterator it //错误
      A::iterator it1 //正确

    3、将两个问题连在一起测试

     1 #include<iostream>                                                                                                         
     2 namespace my{                                                                        
     3                                                                                      
     4   class A_iterator ;                                                                 
     5   class A {                                                                          
     6     public:                                                                          
     7       A(){std::cout << " A is start 
    ";}                                            
     8       ~A(){std::cout << "A is finst 
    ";}                                            
     9       typedef A_iterator iterator;  //我们使用iterator去定义对象,而一般不使用A_iterator 去定义对象
    10   };                                                                                 
    11                                                                                      
    12   class test ;                                                                       
    13   class A_iterator {                                                                 
    14     public:                                                                          
    15       A_iterator(){std::cout << "A_iterator is start 
    ";}                           
    16       ~A_iterator(){std::cout << "A_iterator is finsh 
    ";}                          
    17       typedef test test_type ;        //我们使用test_type去定义对象,而一般不使用test去定义对象                                               
    18   };                                                                                 
    19                                                                                      
    20   class test {                                                                       
    21     public :                                                                         
    22       test(){std::cout << "test is start 
    ";}                                       
    23       ~test(){std::cout << "test is finst 
    ";}                                      
    24   };                                                                                 
    25                                                                                      
    26 }                                                                                    
    27 int main()                                                                           
    28 {                                                                                    
    29   my::A::iterator it ; //没有问题,作用域限定全                                       
    30   //my::iterator it2;  //有问题,my下面没有iterator ,应该在my::A 下面                
    31   my::A::iterator::test_type t1 ; //没有问题,my命令空间中有iterator,iterator下面有test_type
    32   //using namespace my //没有问题,因为my命名空间所有东西都引入进来。                
    33   using my::A;         //没有问题,my是命名空间,A是类,只引入A类中的东西                                
    34   //using my::A::iterator; //有问题,A是类,不是命名空间不能使用。(注意:倒数第二个作用域后面一定要是命名空间)
    35   A::iterator tt2;  //没有问题                                                       
    36   A::iterator::test_type tt3; //没有问题                                             
    37   //iterator::test_type t2 ;                                                         
    38   return 0;                                                                          
    39 } 
     1 #include<iostream>                                                                                                         
     2 class B;                                                                             
     3 class A {                                                                            
     4   public:                                                                            
     5     typedef B b;                                                                     
     6 };                                                                                   
     7                                                                                      
     8 class B{                                                                             
     9   public:                                                                            
    10 };                                                                                   
    11                                                                                      
    12 int main()                                                                           
    13 {                                                                                    
    14   using ::A ;                                                                        
    15   A::b ins ;                                                                         
    16   //b ins2 ; //有问题,需要类名限定                                                   
    17   return 0;                                                                          
    18 } 

    4、总结:

      ①using A::B::C::D 时,D之前必须为命名空间。

        D如果是个类就可以用D::something使用,使用something必须加D::。    

      ②using namespace A::B::C::D 时,D也要为命名空间。

        D里面所有东西都引入了,可以使用命名空间,不加D::作用域

      ③在这就不难解释std::vector<int>::iterator it 

        std是命名空间,vector<>类模板,iterator是vector<>中的一个typedef

      ④类里面是一个作用域,但类不是命名空间。所以类可以被放在using最后一个命令空间的作用域下面(同时它也必须在一个命名空间下面)才能被using。

      ⑤using std::cout ; 这里应该是引入一个对象,在std命令空间里面有个cout(对象),cout就是一个对象。他是一个ostream类型(或至少它的类型是继承自ostream)

    5、故事继续(using在子类中的使用,上面并没有这种用法,看了一些博客,最主要介绍的是using在private继承下的使用,这也很好,但这里还是谈谈public继承下面的使用)(effect c++第33条 A void hiding inherited names)

    #include<iostream>                                                                
    class A {                                                                         
      public:                                                                         
        void virtual fun1(){std::cout << "I am in base fun1
    ";}                              
        void virtual fun1(int a){std::cout << "I am in base fun1_int
    ";}                     
    };                                                                                
    class B : public A{                                                               
      public :                                                                        
        //using A::fun1;  这里如果取消注释,编译通过,正常运行。                                                          
        void virtual fun1(){std::cout << "I am in child fun1 
    ";}   //在这的fun1掩盖了所有基类的同名函数。                        
    };                                                                                
    int main(){                                                                                                                
      int num ;                                                                          
      B b ;                                                                              
      b.fun1();                                                                          
      b.fun1(num);//报错的原因,b中没有匹配到这个函数
     //b.A::fun1(num); //不使用using的情况下,这样访问也没有错误,但是这应该是带有明确目的情况下。这里写出仅仅是为了测试。
    return 0; }

      

      如上图,注释掉using语句后报错了,是因为子类重写了基类的fun1函数,以至于基类所有的fun1都不会被子类访问到。因此b.fun1(num)自然匹配不到相应函数,使用using A::fun1 后基类所有的fun1都引入了子类的作用域,因此就访问到了b.fun1(num)。当然,在这里的b.fun1()当然访问子类的fun1()。

      总结:using在子类中可以引入基类中的成员函数,无论子类是public还是private继承自基类的。

         如果using引入基类的一个函数名,则所有同名函数都会被引入(子类如果重写了则调用时还是用子类的函数)。但如果只想使用基类中的所用同名函数中的一个,则可以使用类作用域限定符加函数名直接使用A::fun1(num);

  • 相关阅读:
    如何用Vault下载.Text 096的源代码
    新增QQ表情
    TortoiseCVS比WinCVS好用多了
    上周热点回顾(5.276.2)
    Couchbase的bug引起的缓存服务器CPU占用高
    云计算之路阿里云上:Linux内核bug引起的“黑色10秒钟”
    上周热点回顾(5.205.26)
    云计算之路阿里云上:拔云见日的那一刻,热泪盈眶
    云计算之路试用Azure:遭遇第一次故障
    上周热点回顾(5.135.19)
  • 原文地址:https://www.cnblogs.com/Ccluck-tian/p/11888436.html
Copyright © 2011-2022 走看看