C++友元函數(超詳細)

2020-07-16 10:04:41
私有成員對於類外部的所有程式部分而言都是隱藏的,存取它們需要呼叫一個公共成員函數,但有時也可能會需要建立該規則的一項例外。

友元函數是一個不屬於類成員的函數,但它可以存取該類的私有成員。換句話說,友元函數被視為好像是該類的一個成員。友元函數可以是常規的獨立函數,也可以是其他類的成員。實際上,整個類都可以宣告為另一個類的友元。

為了使一個函數或類成為另一個類的友元,必須由授予它存取許可權的類來宣告。類保留了它們的朋友的 "名單",只有名字出現在列表中的外部函數或類才被授予存取許可權。通過將關鍵字 friend 放置在函數的原型之前,即可將函數宣告為友元。

友元函數的一般格式如下:

friend <return type><function name> (<parameter type list>);

在 Budget 類的以下宣告中,另一個類的 addBudget 函數 Aux 已宣告為友元:
class Budget
{
    private:
        static double corpBudget;
        double divBudget;
    public:
        Budget() { divBudget = 0; }
        void addBudget(double b)
        {
            divBudget += b;
            corpBudget += divBudget;
        }
        double getDivBudget() const { return divBudget; }
        static double getCorpBudget() { return corpBudget; }
        static void mainOffice(double);
        friend void Aux::addBudget (double) ; // 友元
};
假設另一個 Aux 類代表一個分部的附屬辦公室,也許在另一個國家。附屬辦公室提出了一個單獨的預算要求,該要求必須新增到整個企業的預算中。則 Aux::addBudget 函數的友元宣告告訴編譯器,該函數己授予存取 Budget 的私有成員的許可權。該函數釆用 double 型別的實參,表示要新增到企業預算中的金額: 
class Aux
{
    private:
        double auxBudget;
    public:
        Aux() { auxBudget =0; }
        void addBudget(double);
        double getDivBudget() { return auxBudget; }
};
以下是 Aux addBudget 成員函數的定義:
void Aux::addBudget(double b)
{
    auxBudget += b;
    Budget::corpBudget += auxBudget;
}
形參 b 被新增到企業預算中,這是通過使用表示式 Budget::corpBudget 來存取並實現的。下面的程式演示了這些類在完整程式中的用法。
//auxil.h的內容
#ifndef AUXIL_H
#define AUXIL_H
// Aux class declaration.
class Aux
{
    private:
        double auxBudget;
    public:
        Aux() { auxBudget = 0; }
        void addBudget(double);
        double getDivBudget() const { return auxBudget; }
};
#endif
//budget3.h的內容
#ifndef BUDGET3_H
#define BUDGET3_H
#include "auxil.h" // For Aux class declaration
//Budget class declaration.
class Budget {
    private:
        static double corpBudget;
        double divBudget;
    public:
        Budget() { divBudget =0; }
        void addBudget(double b)
        {
            divBudget += b;
            corpBudget += divBudget;
        }
        double getDivBudget() const {return divBudget;}
        static double getCorpBudget() {return corpBudget;}
        static void mainOffice(double);
        friend void Aux::addBudget(double);
};
#endif

//budget3.cpp的內容
#include "budget3.h"
//Definition of static member.
double Budget::corpBudget = 0;
void Budget:imainOffice(double budReq)
{
    corpBudget += budReq;
}

//auxil.cpp的內容
#include "auxil.h"
#include "budget3.h"
void Aux::addBudget(double b)
{
    auxBudget += b;
    Budget::corpBudget += auxBudget;
}

//main程式的內容
//This program demonstrates a static class member variable. #include <iostream>
#include <iomanip>
#include "budget3.h"
using namespace std;

int main()
{
    const int N_DIVISIONS = 4;
    // Get the budget requests for the divisions and offices
    cout << "Enter the main office's budget request:";
    double amount;
    cin >> amount;
    Budget:imainOffice(amount);
    // Create the division and auxiliary offices
    Budget divisions [N_DIVISIONS];
    Aux auxOffices[N_DIVISIONS];
    cout << "nEnter the budget requests for the divisions and" << "ntheir auxiliary offices as prompted:n";
    for (int count = 0; count < N_DIVISIONS; count++)
    {
        double bud;
        cout << "Division " << (count + 1) << ": ";
        cin >> bud;
        divisions[count].addBudget(bud);
        cout << "Division " << (count + 1) << "'s auxiliary office:";
        cin >> bud;
        auxOffices[count].addBudget(bud);
    }

    // Print the budgets
    cout << setprecision (2);
    cout << showpoint << fixed;
    cout << "Here are the division budget requests:n";
    for (int count = 0; count < N_DIVISIONS; count++)
    {
        cout << "tDivision: " << (count + 1) << "ttt$ ";
        cout << setw(7);
        cout << divisions[count].getDivBudget() << endl;
        cout << "tAuxiliary Office of Division " << (count+1);
        cout << "t$ ";
        cout << auxOffices[count].getDivBudget() << endl;
    }

    // Print total requests
    cout << "tTotal Requests (including main office): $ ";
    cout << Budget::getCorpBudget() << endl;
    return 0;
}
程式輸出結果:

Enter the main office's budget request: 100000
Enter the budget requests for the divisions and their auxiliary offices as prompted:
Division 1: 100000
Division 1's auxiliary office: 500000
Division 2: 200000
Division 2's auxiliary office: 40000
Division 3: 300000
Division 3's auxiliary office: 700000
Division 4: 400000
Division 4's auxiliary office: 650000
Here are the division budget requests:
Division: 1    $ 100000.00
Auxiliary Office of Division 1 $ 50000.00
Division: 2    $ 200000.00
Auxiliary Office of Division 2    $ 40000.00
Division: 3    $ 300000.00
Auxiliary Office of. Division 3    $ 70000.00
Division: 4    $ 400000.00
Auxiliary Office of Division 4    $ 65000.00
Total Requests (including main    office): $ 1325000.00

注意,如前所述,可以使整個類成為另一個類的友元。Budget 類可以通過以下宣告使 Aux 類成為友元:

friend class Aux;

但是,這可能並不是一個好主意,因為這將導致 Aux 的每個成員函數(包括稍後可能新增的函數)都可以存取 Budget 的私有成員。所以,最好的做法是只宣告那些必須有權存取類的私有成員的函數作為友元。