zoukankan      html  css  js  c++  java
  • C++ 内部类

    1.当外部类的成员变量不是类型名称、静态或枚举数时 内部类无法直接使用该成员变量如:

    class YLBASE
    {
    public:
        enum enum_futures_model{continueTwelve = 0,oneFiveNine = 1};
        string m;
        /**********************************************************Date Class********************************************************/
        class Date
        {
        private:
            int year;
            int month;
            int day;
            /*************Private Method****************/
            void addOneDay(); //增加1天
            void subOneDay(); //减少1天
            int subSmallDate(const Date &date) const; //减去一个更小的 Date,返回天数
        public:
            /**********************Construction****************************/
            Date();
            Date(int year,int month, int day);
            ~Date(void);
            /*************Is Bool***********************/
            //    bool isStandForYear;//true Date 包含year month(0) day(0)
            //    bool isStandForMonth;//true Date 包含year month day(0)
            //    bool isStandForDay;//true: Date 包含year month day
            /*************Get Set Method****************/
            void setDate(int year,int month, int day);
            int getYear();
            int getMonth();
            int getDay();
            void setYear(int iyear);
            void setMonth(int imonth);
            void SetDay(int iday);
            /*************Public Method****************/
            int daysPerMonth(int m=-1) const; //每月多少天?
            int daysPerYear(int y=-1) const; //每年多少天?
            int compare(const Date &date) const; //与string中的compare差不多,相等返回0
            bool isLeapYear(int y=-1) const; //是否闰年
            int subDate(const Date &date) const; //减去一个日期,返回天数
            Date subDays(int days) const; //减少指定的天数
            Date addDays(int days) const; //增加指定的天数
            string toString();
            /********** Operator Overloading ***********/
            Date& operator++(); //++ Date
            Date operator++(int); //Date ++
            Date& operator--(); //-- Date
            Date operator--(int); //Date --
            Date operator+(int days); //Date + days
            Date operator-(int days); //Date - days
            int operator-(const Date &date); //Date1 - Date2
            bool operator < (const Date& d) const;
            bool operator()(const Date& d1, const Date& d2) const;
            bool operator == (const Date& d ) const;
        };

    YLBASE 为外部类 DATE为内部类 在DATE中可以直接使用 YLBASE 定义的enum_futures_model,但无法直接使用m。要在内部类可以直接使用外部类的成员变量,可参考以下代码

    class outclass  
    {  
    public:  
        int m;  
        class inclass//内部类通过parent指针访问外部类的成员,包括public、private  
        {  
        public:  
            void set_m(int i)  
            {  
                outclass *parent = (outclass *) ((char*)this - offsetof(outclass,in));   
                parent->m = i;  
            }  
        }in;  
      
      
    };  
      
    void main()  
    {  
        outclass out;  
        out.in.set_m(123);  
        cout << out.m << endl;  
        system("pause");  
    } 

    总结:

    虽然内部类在外部类内部定义,但它是一个独立的类,基本上与外部类不相关。它的成员不属于外部类,同样,外部类的成员也不属于该内部类。内部类的出现只是告诉外部类有一个这样的类型成员供外部类使用。并且,外部类对内部类成员的访问没有任何特权,内部类对外部类成员的访问也同样如此,它们都遵循普通类所具有的标号访问控制。
     
       若不在内部类内部定义其成员,则其定义只能写到与外部类相同的作用域中,且要用外部类进行限定,不能把定义写在外部类中。例如,内部类的静态成员就是这样的一个例子。

    2.内部类的好处

    内 部 类 是 嵌 套 类( n e t s t e d c l a s s )
    的 一 种。 和 类的 其 他 成 员 一 样, 嵌 套 类 也 可以 被 声明 为 静 态 或 者
    非 静 态的 。 静态 嵌 套 类, 也 被 称为 顶 层 嵌 套 类( t o p - l e v e l n e s t e dc l a s s ) , 非静 态的 嵌套 类称 为内 部 类( i n n e r c l a s s ) 。 静 态 嵌套 类
    只 是 提 供了 代 码 组 织的 一 种 便 利 , 作 用 类似于 C + + 中 的 命名 空
    间。 嵌套 类最重 要的 类型 是 内 部类。
    一 个内 部 类 对 象 可以 访问 创建 它的 外 部 类对 象的 内 容 , 包
    括私 有变 量 , 这是 一 个非常 有用的 特 性 , 为系 统设 计提 供 了 更
    多的 思 路和 方 法。 要 想实 现 这 个 特 性 , 内 部 类 对象 就必 须有 指
    向 外 部 类 对 象 的 引 用 。 J a v a 编 译 器 在 创 建内 部 类 对 象 时, 隐 式
    的 把其 外部类对象的 引 用 也传了 进 去并一直保 存着。 这样就使
    得内 部 类 对 象 始 终 可以 访问 其 外部 类 对 象 , 同 时 这 也是 为 什么
    在外部类作用范围 之外向 要创建 内 部类对象必须先创建其外
    部 类 对 象的 原因。
    在 C + + 中 要 模 拟 实 现 内 部 类 机 制, 需 要 借 助 于 C + 十 的 嵌 套
    类。 同 时, 内 部 类的 对 象 需 要 保 存一 个 对于 其 包围 类对 象的 引
    用或 者 指 针, 而 且, 为了 使内 部 类 对 象 能 够 访间 外 部 类 对 象的
    私 有 变 量 和 方 法, 需 要 将内 部 类 声 明 为 外 部 类的 友 元 类。 具 体
    的 实 现方法和 使 用场景如下 所 示 :

    #include <iostream>
    #include <string>
    using namespace std;
    //接口lAnibi
    struct IAmbi
    {
    virtual void ambi()=0;
    };
    //接口IPingable
    struct IPingable:public IAmbi{
    virtual void ping()=0;
    virtual void ambi()=0;
    }
    //接口IPangable
    struct IPangable:public IAmbi{
    virtualvoidpang()=0;
    virtualvoidambi()=0;
    };
    void callPing(IPingable & p){
    p.pmg();
    p.ambi();
    }
    void callPang(IPangable & b){
    b.pang);
    b.ambi();
    }
    class PingPang:public IPingable{
    //包围类PingPang的私有变量
    string content_private;
    //声明内部类Inner并将它声明为PingPang的友类
    class Inner;
    friend class Inner;
    class Inner:publicIPangable〔
    //内部类保存一个其包围类的指针或者引用
    PingPang*parent;
    public:
    Inner(PingPang*p):parent(p){}
    //内部类可以访问其包围类的私有变量(此处为content_private)
    void pang(){
    cout<<"pangcalledforinnerof'<<parent->content-private<<end
    }
    //此虚拟函数的签名和其包围类的相同,不存在名称歧义,以独立重新改写
    void ambi()(
    cout<<"ambicalledforinner"<<endl;
    }inner;
    public:
    PingPang(const string& str):content_private(str)Iinner(this){}
    void ping()(cout<<"pingcalledforouter"<<endl;)
    void ambi()(cout<<"ambicalledforouter"<<endl;)
    //返回由内部类实现的接口IPangable的引用
    operator IPangable&(){returninner;)
    );
    int main(intargc,char*argv[])
    {
    PingPang x("PingPang");
    /此处的效果类似于把PingPang这个类upcast到两个基类
    callPing(x);
    callPang(x);
    return 0;
    }

    
    
  • 相关阅读:
    MySQL中mysqldump导出数据的使用
    MySQL中show语法使用总结
    Nginx配置项优
    Elasticsearch5.2.2安装
    SSH实现双向认证
    MySQL5.6主从复制搭建基于日志(binlog)
    清除Pycharm设置的方法
    Python3编程技巧
    django组件-中间件
    Python打杂之路
  • 原文地址:https://www.cnblogs.com/yelongsan/p/4187358.html
Copyright © 2011-2022 走看看