91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++中友元類和嵌套類如何使用

發布時間:2022-08-25 11:35:05 來源:億速云 閱讀:154 作者:iii 欄目:開發技術

今天小編給大家分享一下C++中友元類和嵌套類如何使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

前言

友元這個詞,在學習類的時候肯定接觸過,但是當時我們只用了很多友元函數。

友元有三種:

  • 友元函數

  • 友元類

  • 友元類方法

類并非只能擁有友元函數,也可以將類作為友元。在這種情況下,友元類的所以方法都能訪問原始類的私有成員和保護成員。另外,也可以做更嚴格的限制,只將特定的成員函數指定為另一個類的友元。

1. 友元類

假如我們有兩個類:Tv電視機類,Remote遙控器類。那么這兩個類是什么關系呢?既不是has-a關系,也不是 is-a關系,但是我們知道遙控器可以控制電視機,那么遙控器必須能夠訪問電視機的私有或保護數據。所以,遙控器就是電視機的友元。

類似于友元函數的聲明,友元類的聲明:

friend class Remote;

友元聲明可以位于公有、私有或保護部分,其所在的位置無關緊要。

下面是代碼實現:

//友元類1.h
#ifndef TV_H_
#define TV_H_
class Tv
{
private:
    int state;//On or Off
    int volume;//音量
    int maxchannel;//頻道數
    int channel;//頻道
    int mode;//有線還是天線,Antenna or Cable
    int input;//TV or DVD
public:
    friend class Remote;
    enum{Off,On};
    enum{MinVal,MaxVal=20};
    enum{Antenna,Cable};
    enum{TV,DVD};
    Tv(int s=Off,int mc=125):state(s),volume(5),maxchannel(mc),
                    channel(2),mode(Cable),input(TV){}
    void onoff(){state=(state==On)?Off:On;}
    bool ison() const{return state==On;}
    bool volup();
    bool voldown();
    void chanup();
    void chandown();
    void set_mode(){mode=(mode==Antenna)?Cable:Antenna;}
    void set_input(){input=(input==TV)?DVD:TV;}
    void settings() const;//display all settings
};
class Remote
{
private:
    int mode;//控制TV or DVD
public:
    Remote(int m=Tv::TV):mode(m){};
    bool volup(Tv & t){return t.volup();}
    bool voldown(Tv & t){return t.voldown();}
    void onoff(Tv &t){t.onoff();}
    void chanup(Tv &t){t.chanup();}
    void chandown(Tv &t){t.chandown();}
    void set_chan(Tv &t,int c){t.channel=c;}
    void set_mode(Tv &t){t.set_mode();}
    void set_input(Tv &t){t.set_input();}
};
#endif
//友元類1.cpp
#include"友元類1.h"
#include<iostream>
bool Tv::volup()
{
    if(volume<MaxVal)
    {
        volume++;
        return true;
    }
    else
        return false;
}
bool Tv::voldown()
{
    if(volume>MinVal)
    {
        volume--;
        return true;
    }
    else
        return false;
}
void Tv::chanup()
{
    if(channel<maxchannel)
        channel++;
    else 
        channel=1;
}
void Tv::chandown()
{
    if(channel>1)
        channel--;
    else
        channel=maxchannel;
}
void Tv::settings() const
{
    using std::cout;
    using std::endl;
    cout<<"Tv is "<<(state==Off? "Off":"On")<<endl;
    if(state==On)
    {
        cout<<"Volume setting = "<<volume<<endl;
        cout<<"Channel setting = "<<channel<<endl;
        cout<<"Mode = "
            <<(mode==Antenna?"antenna":"cable")<<endl;
        cout<<"Input = "
            <<(input==TV?"TV":"DVD")<<endl;
    }
}
//友元類1main.cpp
#include<iostream>
#include"友元類1.h"
int main()
{
    using std::cout;
    Tv s42;
    cout<<"Initial setting for 42\" TV:\n";
    s42.settings();
    s42.onoff();
    s42.chanup();
    cout<<"\nAdjusted settings for 42\" TV:\n";
    s42.settings();
    Remote grey;
    grey.set_chan(s42,10);
    grey.volup(s42);
    grey.volup(s42);
    cout<<"\n42\" settings after using remote:\n";
    s42.settings();
    Tv s58(Tv::On);
    s58.set_mode();
    grey.set_chan(s58,28);
    cout<<"\n58\" settings:\n";
    s58.settings();
    return 0;
}

PS D:\study\c++\path_to_c++> g++ -I .\include\ -o 友元類1 .\友元類1.cpp .\友元類1main.cpp
PS D:\study\c++\path_to_c++> .\友元類1.exe
Initial setting for 42" TV:  
Tv is Off

Adjusted settings for 42" TV:
Tv is On
Volume setting = 5
Channel setting = 3
Mode = cable
Input = TV

42" settings after using remote:
Tv is On
Volume setting = 7
Channel setting = 10
Mode = cable
Input = TV

58" settings:
Tv is On
Volume setting = 5
Channel setting = 28
Mode = antenna
Input = TV

總之,友元類和友元函數很類似,不需要過多說明了。

2. 友元成員函數

在上面那個例子中,我們知道大部分Remote方法都是用Tv類的公有接口實現的。這意味著這些方法不是真正需要作為友元。事實上,只有一個直接訪問Tv的私有數據的Remote方法即Remote::chan(),因此它才是唯一作為友元的方法。我們可以選擇僅讓特定的類成員成為另一個類的友元,而不必讓整個類成為友元,但這樣做會有一些麻煩。

Remote::chan()成為Tv類的友元的方法是,在Tv類聲明中將其聲明為友元:

class Tv
{
    friend void Remote::set_chan(Tv & t,int c);
    ...
}

但是,編譯器能處理這條語句,它必須知道Remote的定義。否則,它就不知道Remote::set_chan是什么東西。所以我們必須把Remote的聲明放到Tv聲明的前面。但是Remote聲明中同樣提到了TV類,那么我們必須把TV聲明放到Remote聲明的前面。這就發生了循環依賴。我們得使用 前向聲明(forward declaration) 來解決這一問題。

class Tv;
class Remote{...};
class Tv{...};

但是,還有一點麻煩需要解決:Remote的類聲明中不能直接給出成員函數的定義了,因為這些函數會訪問Tv類成員,而Tv類的成員的聲明是Remote類的后面的。那么我們必須在Remote的類聲明外給出方法定義。

代碼實現:

//友元成員函數1.h
#ifndef TVFM_H_
#define TVFM_H_
class Tv;
class Remote
{
public:
    enum{Off,On};
    enum{MinVal,MaxVal=20};
    enum{Antenna,Cable};
    enum{TV,DVD};
private:
    int mode;//控制TV or DVD
public:
    Remote(int m=TV):mode(m){};
    bool volup(Tv & t);
    bool voldown(Tv & t);
    void onoff(Tv &t);
    void chanup(Tv &t);
    void chandown(Tv &t);
    void set_chan(Tv &t,int c);
    void set_mode(Tv &t);
    void set_input(Tv &t);
};
class Tv
{
private:
    int state;//On or Off
    int volume;//音量
    int maxchannel;//頻道數
    int channel;//頻道
    int mode;//有線還是天線,Antenna or Cable
    int input;//TV or DVD
public:
    friend void Remote::set_chan(Tv &t,int c);
    enum{Off,On};
    enum{MinVal,MaxVal=20};
    enum{Antenna,Cable};
    enum{TV,DVD};
    Tv(int s=Off,int mc=125):state(s),volume(5),maxchannel(mc),
                    channel(2),mode(Cable),input(TV){}
    void onoff(){state=(state==On)?Off:On;}
    bool ison() const{return state==On;}
    bool volup();
    bool voldown();
    void chanup();
    void chandown();
    void set_mode(){mode=(mode==Antenna)?Cable:Antenna;}
    void set_input(){input=(input==TV)?DVD:TV;}
    void settings() const;//display all settings
};
inline bool Remote::volup(Tv & t){return t.volup();}
inline bool Remote::voldown(Tv & t){return t.voldown();}
inline void Remote::onoff(Tv &t){t.onoff();}
inline void Remote::chanup(Tv &t){t.chanup();}
inline void Remote::chandown(Tv &t){t.chandown();}
inline void Remote::set_chan(Tv &t,int c){t.channel=c;}
inline void Remote::set_mode(Tv &t){t.set_mode();}
inline void Remote::set_input(Tv &t){t.set_input();}
#endif

之前我們說過,內聯函數的鏈接性是內部的,這就意味著函數定義必須在使用函數的文件中。在上面的代碼中,內聯函數的定義位于頭文件中。當然你也可以將定義放在實現文件中,但必須刪除關鍵字inline,這樣函數的鏈接性將是外部的。

還有就是,我們直接讓整個Remote類成為友元并不需要前向聲明,因為友元語句已經指出Remote是一個類:

friend class Remote;

總之,不推薦使用友元成員函數,使用友元類完全可以達到相同的目的。

3. 其他友元關系

3.1 成為彼此的友元類

還是電視機和遙控器的例子,我們知道遙控器能控制電視機,但是我告訴你,現代電視機也是可以控制遙控器的。例如,我們現在可以在電視上玩角色扮演游戲,當你控制的角色從高處落入水中時,遙控器(手柄)會發出振動模擬落水感。那么,遙控器是電視機的友元,電視機也是遙控器的友元,那么它們互為友元。

class Tv
{
friend class Remote;
public:
    void buzz(Remote & r);
    ...
};
class Remote
{
friend class Tv;
public:
    void bool volup(Tv &t){t.volup();}
    ...
};
inline void Tv::buzz(Remote &r)
{
    ...
}

這里buzz函數的定義必須放到Remote類聲明的后面,因為buzz的定義中會使用到Remote的成員。

3.2 共同的友元

使用友元的另一種情況是,函數需要訪問兩個類的私有數據,那么必須這樣做:函數既是一個類的友元也是另一個類的友元.

例如,有兩個類AnalyzerProbe,我們需要同步它們的時間成員:

class Analyzer;
class Probe
{
    friend void sync(Analyzer & a,const Probe &p);
    friend void sync(Probe &p,const Analyzer &a);
};
class Probe
{
    friend void sync(Analyzer & a,const Probe &p);
    friend void sync(Probe &p,const Analyzer &a);
};
inline void sync(Analyzer & a,const Probe &p)
{
    ...
}
inline void sync(Probe &p,const Analyzer &a)
{
    ...
}

4. 嵌套類

在C++中我們可以將類聲明放在另一個類中。在另一個類中聲明的類被稱為嵌套類。

實際上,嵌套類很簡單,它的原理和類中聲明結構體、常量、枚舉、typedef、名稱空間是一樣的,這些技術我們一直都在使用。

對類進行嵌套和包含是不一樣的。包含意味著將類對象作為另一個類的成員,而對類進行嵌套不創建類成員,而是定義了一種類型,該類型僅在包含嵌套類的類中有效。

一般來說我們使用嵌套類是為了幫助實現另一個類,并避免名稱沖突

嵌套類的作用域和訪問控制

作用域

如果嵌套類是在另一個類的私有部分聲明的,那么只能在后者的類作用域中使用它,派生類以及外部世界無法使用它。

如果嵌套類是在另一個類的保護部分聲明的,那么只能在后者、后者的派生類的類作用域中使用該嵌套類,外部世界無法使用它。

如果嵌套類是在另一個類的公有部分聲明的,那么能在后者、后者的派生類和外部世界中使用它。

class Team
{
public:
    class Coach{...}
    ...
};

上面的Coach就是一個公有部分的嵌套類,那么我們可以這樣:

Team::Coach forhire;

總之,嵌套類的作用域和類中聲明結構體、常量、枚舉、typedef、名稱空間是一樣。但是對于枚舉量來說,我們一般把它放在類的公有部分,例如ios_base類中的各種格式常量:ios_base::showpoint等。

訪問控制

嵌套類的訪問控制和常規類是一模一樣的,嵌套類也有public,private,protected,只有公有部分對外部世界開放。

例如:

class A
{
    class B
    {
    private:
        int num;
    public 
        void foo();
    };
};

則在A的類作用域中,可以創建B對象,并使用B.foo()方法。

看看一個類模板中使用嵌套類的例子:

#ifndef QUEUETP_H_
#define QUEUETP_H_
template<typename Item>
class QueueTP
{
private:
    enum{Q_SIZE=10};
    class Node
    {
    public:
        Item item;
        Node *next;
        Node(const Item & i):item(i),next(0){}
    };
    Node *front;
    Node *rear;
    int items;
    const int qsize;
    QueueTP(const QueueTP &q):qsize(0){}//搶占定義,賦值構造函數
    QueueTP & operator=(const QueueTP &q){return *this;}//搶占定義
public:
    QueueTP(int qs=Q_SIZE):qsize(qs)
    {
        front = rear =0;
        items=0;
    }
    ~QueueTP()
    {
        Node* temp;
        while (front !=0)
        {
            temp=front;
            front=front->next;
            delete temp;
        }
    }
    bool isempty() const
    {
        return items==0;
    }
    bool isfull() const
    {
        return items==qsize;
    }
    int queuecount() const
    {
        return items;
    }
    bool enqueue(const Item & item)
    {
        if(isfull())
            return false;
        Node * add = new Node(item);
        items++;
        if(front==0)
            front=add;
        else
            rear->next=add;
        rear=add;
        return true;
    }
    bool dequeue(Item &item)
    {
        if(front==0)
            return 0;
        item=front->item;
        items--;
        Node * temp=front;
        front=front->next;
        delete temp;
        if(items==0)
            rear=0;
        return true;
    }
};
#endif

以上就是“C++中友元類和嵌套類如何使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

广昌县| 西藏| 尼勒克县| 偃师市| 紫阳县| 江津市| 大悟县| 徐汇区| 阿拉尔市| 酒泉市| 平远县| 安吉县| 申扎县| 铁岭县| 澄迈县| 怀仁县| 墨脱县| 托里县| 扎鲁特旗| 九龙县| 岗巴县| 兴安盟| 泗洪县| 上虞市| 磴口县| 根河市| 疏附县| 昔阳县| 罗甸县| 禄丰县| 肥城市| 慈溪市| 鄂伦春自治旗| 宿松县| 陈巴尔虎旗| 金寨县| 行唐县| 韶山市| 抚宁县| 思茅市| 军事|