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;
}

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM