zoukankan      html  css  js  c++  java
  • C++学习之嵌套类和局部类

    C++学习之嵌套类和局部类
          

    局部类

            在一个函数体内定义的类称为局部类。 局部类中只能使用它的外围作用域中的对象和函数进行联系,因为外围作用域中的变量与该局部类的对象无关。在定义局部类时需要注意:局部类中不能说明静态成员函数,并且所有成员函数都必须定义在类体内在实践中,局部类是很少使用的。下面是一个局部类的例子。

    int a;

    void fun()

    {

      static int s;

    class A

    {

      public:

      void init(int i) { s = i; }

    };

    A m;

      m.init(10);

    }

    嵌套类理解

           在一个类中定义的类称为嵌套类,定义嵌套类的类称为外围类。定义嵌套类的目的在于隐藏类名,减少全局的标识符,从而限制用户能否使用该类建立对象。这样可以提高类的抽象能力,并且强调了两个类 (外围类和嵌套类) 之间的主从关系。

    class A

    {

     public:

        class B 

    {   

    public:

          …

        private:

          …

        };

        void f();

    private:

        int a;

    }

    其中,类B是一个嵌套类,类A是外围类,类B定义在类A的类体内。

    对嵌套类的若干说明:

    1、从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类的作用域内使用该类名时,需要加名字限定。

    2、从访问权限的角度来看,嵌套类名与它的外围类的对象成员名具有相同的访问权限规则。不能访问嵌套类的对象中的私有成员函数,也不能对外围类的私有部分中的嵌套类建立对象。

    3、嵌套类中的成员函数可以在它的类体外定义。

    4、嵌套类中说明的成员不是外围类中对象的成员,反之亦然。嵌套类的成员函数对外围类的成员没有访问权,反之亦然。

    在分析嵌套类与外围类的成员访问关系时,往往把嵌套类看作非嵌套类来处理。这样,上述的嵌套类可写成如下格式:

    class A

    {  public:

        void f();

      private:

        int a;

    };

    class B

    {

     public:

       …

    private:

      …

    };  [ 嵌套类的理解形式 ]

     

    5、在嵌套类中说明的友元对外围类的成员没有访问权。

    6、如果嵌套类比较复杂,可以只在外围类中对嵌套类进行声明,关于嵌套的详细的内容可在外围类体外的文件域中进行定义。(理解这句话)

    嵌套类规则详细分析

    1、嵌套类的名字只在外围类可见

           在一个类的内部定义另一个类,我们称之为嵌套类(nested class),或者嵌套类型。之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现。

           虽然嵌套类在外围类内部定义,但它是一个独立的类,基本上与外围类不相关。它的成员不属于外围类,同样,外围类的成员也不属于该嵌套类嵌套类的出现只是 告诉外围类有一个这样的类型成员供外围类使用。并且,外围类对嵌套类成员的访问没有任何特权,嵌套类对外围类成员的访问也同样如此,它们都遵循普通类所具有的标号访问控制。

          若不在嵌套类内部定义其成员,则其定义只能写到与外围类相同的作用域中,且要用外围类进行限定,不能把定义写在外围类中例如,嵌套类的静态成员就是这样的一个例子。(如何完成?)

           前面说过,之所以使用嵌套类的另一个原因是达到底层实现隐藏的目的。为了实现这种目的,我们需要在另一个头文件中定义该嵌套类,而只在外围类中前向声明这个嵌套类即可。当然,在外围类外面定义这个嵌套类时,应该使用外围类进行限定。使用时,只需要在外围类的实现文件中包含这个头文件即可。

          另外,嵌套类可以直接引用外围类的静态成员、类型名和枚举成员,即使这些是private的。一个好的嵌套类设计:嵌套类应该设成私有。嵌套类的成员和方法可以设为public

    嵌套类名字的解析过程

    嵌套类定义的名字解析过程:

    出现在名字使用点前的嵌套类的声明。

    出现在名字使用点前外围类的声明。

    嵌套类定义前名字空间域的声明。

    嵌套类的成员定义中的名字解析过程:

    成员函数局部声明。

    嵌套类成员的声明。

    外围类成员的声明。

    成员函数定义前名字空间域中出现的声明。

    参考实例

    #include <iostream>

    using namespace std;

    class A

    {

    private:

     int n;

    public:

     A(int n)

     {

      this->n=n;

      cout<<"Aconstructor"<<endl;

     }

    voidshow();

    class B

    {

     public:

          B( )

          {

          cout<<"B constructor"<<endl;

          }

     

    voiddisp()

        {

          cout<<"B disp"<<endl;

        }

    };

    Bb;

    };

    voidA::show()

    {

     cout<<n<<endl;

    }

    void main()

    {

     A a(1);

     a.show();

     a.b.disp();

    }

    class Outter

    {

    // friend class Inner 加了这行也白搭

    (理解为什么)正确写法应该是;

    protected:

    voidFoo(){}

    private:

    voidFoo2(){}

    public:

    voidFoo3(){}

    private:

    classInner

    {

    Inner(Outter*pFather)

    {

    pFather->Foo();// Error, compiler complain !!

    pFather->Foo2();//Error, compiler complain !!

    pFather->Foo3();//OK !
    }

    };

    };

    嵌套的结构(当然包括类)并不能自动获得访问private成员的权限,要获得的话,必须遵守特定的规则:首先声明(不是定义)一个嵌套结构,然后声明它是全局范围使用的一个friend,最后定义这个结构结构的定义必须与friend声明分开,否则不会把它看做成员

    改成这样,就可以通过编译了
    class Outter

    {

    protected:

    voidFoo(){};

    private:

    voidFoo2(){};

    public:

    voidFoo3(){};

    private:

    class Inner; // 声明  (是否可以省略声明?不可以)

    friend Inner; // 声明为友元

    classInner

    {

    Inner(Outter*pFather)

    {

    pFather->Foo();

    pFather->Foo2();

    pFather->Foo3();

    }

    };

    };

  • 相关阅读:
    小试SQLServer中的CLR特性
    转:memcached命令行参数说明
    2012年9月19日最新整理的日本产品(日货)名单!
    转:Memcached Java Client API详解
    刚写的一个小案例,实现多选的添加及删除
    SVG中的常用标签
    转:网页启用Gzip压缩 提高浏览速度
    SVG案例:著名的PostScript老虎图片
    SVG文档:SVG编程经典教程(转)
    实用技巧:利用SQL Server的扩展属性自动生成数据字典
  • 原文地址:https://www.cnblogs.com/sunfie/p/4394591.html
Copyright © 2011-2022 走看看