1. 程式人生 > >C++ 友元函式的使用&過載“輸入輸出”運算子

C++ 友元函式的使用&過載“輸入輸出”運算子

友元函式

形式

friend 型別名 友元函式名(形參表);

然後在類體外對友元函式進行定義,定義的格式和普通函式相同,但可以通過物件作為引數直接訪問物件的私有成員

說明如下

1)必須在類的說明中說明友元函式,說明時以關鍵字friend開頭,後跟友元函式的函式原型,友元函式的說明可以出現在類的任何地方,包括在private和public部分;

2)注意友元函式不是類的成員函式,所以友元函式的實現和普通函式一樣,在實現時不用"::"指示屬於哪個類,只有成員函式才使用"::"作用域符號;

3)友元函式不能直接訪問類的成員,只能訪問物件成員,

4)友元函式可以訪問物件的私有成員,但普通函式不行;

5)呼叫友元函式時,在實際引數中需要指出要訪問的物件,

6)類與類之間的友元關係不能繼承。

7)一個類的成員函式也可以作為另一個類的友元,但必須先定義這個類。

友元函式使用的一個例子,摘自 C++ primer 中文版 第6版:

#include <iostream>
#include <string>

using namespace std;

class Time
{

private:
    int hours;
    int minutes;

public:
    Time();
    Time(int h, int m = 0);
    void AddMin(int m);
    void AddHr(int h);
    void Reset(int h = 0, int m = 0);
    Time operator+(const Time &t)const;
    Time operator-(const Time &t)const;
    Time operator*(double n)const;
    friend Time operator*(double mult, const Time &t);/* friend function */
    /*std::ostream& */
    friend ostream & operator<<(ostream & os, const  Time &t);/* friend function  */
    void Show()const;
    
};

Time::Time()
{
    hours = minutes = 0;
}

Time::Time(int h, int m)
    :hours(h),minutes(m)
{
}

void Time::AddMin(int m)
{
    minutes += m;
    hours += minutes/60;
    minutes %= 60;
}

void Time::AddHr(int h)
{
    hours  += h;
}

void Time::Reset(int h, int m)
{
    hours = h;
    minutes = m;
}

Time Time::operator+(const Time &t)const
{
    Time sum;
    sum.minutes = t.minutes + this->minutes;
    sum.hours = t.hours + this->hours + (sum.minutes / 60);
    sum.minutes %= 60;

    return sum;/* 不能返回區域性變數的引用 */
}

Time Time::operator-(const Time &t)const
{
    Time des;
    int tm1, tm2;

    tm1 = t.minutes + t.hours * 60;
    tm2 = this->minutes + this->hours * 60;

    des.minutes = (tm2 - tm1) % 60;
    des.hours = (tm2 - tm1) / 60;

    return des;
}

Time Time::operator*(double mult)const
{
    Time res;

    long ttmin = (this->hours * 60 + minutes) * mult;

    res.hours = ttmin / 60;
    res.minutes = ttmin % 60;

    return res;
}


void Time::Show()const
{
    cout<<hours<<" hours "<<minutes<<" minutes "<<endl;
}

/* friend union */

/* 由於成員函式運算子*的表示式方式是 Time * double ,但是有時候我們會寫成 double * Time 的格式  
這時候編譯器不會呼叫 operator*,因為左側的運算元不是物件。
解決這種問題的方式是使用友元:
1.宣告友元函式
2.建立友元函式

*/

inline Time operator*(double mult, const Time &t)
{
    
    return t * mult;
}

/* 有了友元函式,就可以運算表示式 double * Time                          */

/*  常用友元:過載 <<運算子        */

std::ostream & operator<<(std::ostream &os, const Time &t)
{
    os<<t.hours<<" hours "<<t.minutes<<" minutes ";
    return os;/* 呼叫後返回cout物件,後續的cout才能正常工作 ,詳見 C++primer 6 中文版394頁                   */
}





int main()
{
    Time weeding(4, 35);
    Time waxing(2, 47);

    Time total;
    Time des;
    Time adjusted;

    cout<<"weeding time = ";
    weeding.Show();
    cout<<endl;

    cout<<"waxing time = ";
    waxing.Show();
    cout<<endl;

    cout<<"total work time =";
    total = waxing + weeding;
    total.Show();
    cout<<endl;

    cout<<"weeding time - waxiang time = ";
    des = weeding - waxing;
    des.Show();
    cout<<endl;

    cout<<"adjustice 1.5 times work time = ";
    adjusted = total * 1.5;
    adjusted.Show();
    cout<<endl;

    Time aida(3, 35);
    Time tosca(2, 48);

    Time temp;

    cout<<"Aida and Tosca:\n";
    cout<<aida<<" ; "<<tosca<<endl;

    temp = aida + tosca;
    cout<<"Aida + Tosca = "<<temp<<endl;

    temp = aida * 1.17;
    cout<<"Aida * 1.7 = "<<temp<<endl;

    cout<<"10 *  Tosca = "<< 10 * tosca<<endl;
    
    

    return 0;
    
}

運算結果:

[email protected]:~/C++$ ./friend 
weeding time = 4 hours 35 minutes 

waxing time = 2 hours 47 minutes 

total work time =7 hours 22 minutes 

weeding time - waxiang time = 1 hours 48 minutes 

adjustice 1.5 times work time = 11 hours 3 minutes 

Aida and Tosca:
3 hours 35 minutes  ; 2 hours 48 minutes 
Aida + Tosca = 6 hours 23 minutes 
Aida * 1.7 = 4 hours 11 minutes 
10 *  Tosca = 28 hours 0 minutes 
 

關於過載運算子<<:上邊程式的例子中使用友元過載<<

C++ 能夠使用流提取運算子 >> 和流插入運算子 << 來輸入和輸出內建的資料型別。您可以過載流提取運算子和流插入運算子來操作物件等使用者自定義的資料型別。

在這裡,有一點很重要,我們需要把運算子過載函式宣告為類的友元函式,這樣我們就能不用建立物件而直接呼叫函式。

下面的例項演示瞭如何過載提取運算子 >> 和插入運算子 <<:

#include <iostream>
using namespace std;
 
class Distance
{
   private:
      int feet;             // 0 到無窮
      int inches;           // 0 到 12
   public:
      // 所需的建構函式
      Distance(){
         feet = 0;
         inches = 0;
      }
      Distance(int f, int i){
         feet = f;
         inches = i;
      }
      friend ostream &operator<<( ostream &output, 
                                       const Distance &D )
      { 
         output << "F : " << D.feet << " I : " << D.inches;
         return output;            
      }
 
      friend istream &operator>>( istream  &input, Distance &D )
      { 
         input >> D.feet >> D.inches;
         return input;            
      }
};
int main()
{
   Distance D1(11, 10), D2(5, 11), D3;
 
   cout << "Enter the value of object : " << endl;
   cin >> D3;
   cout << "First Distance : " << D1 << endl;
   cout << "Second Distance :" << D2 << endl;
   cout << "Third Distance :" << D3 << endl;
 
 
   return 0;
}

相關推薦

C++ 函式的使用&過載輸入輸出運算子

友元函式 形式 friend 型別名 友元函式名(形參表); 然後在類體外對友元函式進行定義,定義的格式和普通函式相同,但可以通過物件作為引數直接訪問物件的私有成員 說明如下 1)必須在類的說明中說明友元函式,說明時以關鍵字friend開頭,後跟友元函式的函

C++模板類與運算子作為函式過載

我自定義了一個模板類並重載了運算子,預定義實現功能為能實現對陣列一般操作,類似於vector。 #ifndef ARRAY_H #define ARRAY_H #include <iostream> using namespace std; templa

C++運算子過載函式過載

實驗要求: 1、設計一個類,用自己的成員函式過載運算子,使對整型的運算子=、+、-、*、/ 適用於分數運算。要求: (1)輸出結果是最簡分數(可以是帶分數); (2)分母為1,只輸出分子。 #include<iostream> using

C++過載(2):通過成員函式函式過載

分別通過成員函式和友元函式完成過載 #include <iostream> using namespace std; class Complex { public: Complex(double real =0,double imag=0):real(real),imag(i

成員函式過載運算子函式過載運算子的比較

下面的例子可以很好的說明定義為friend   function的好處.      #include   <iostream.h>      class   point      {              int   x;              int   y;             

定義一個複數類,用函式實現對雙目運算子“ + ”的運算子過載, 使其適用於複數運算

////定義一個複數類,用友元函式實現對雙目運算子“ + ”的運算子過載,////使其適用於複數運算//#include<iostream>using namespace std;class Complex{private:int real;int imag;pu

函式過載操作符

當使用namespace std的時候會出現訪問不了私有成員的錯誤,不使用std便沒有錯誤。奇怪的是之前的程式使用的std也沒有錯誤,不知為何  #ifndef STRING_H_ #define STRING_H_ #include <iostream> //

C# 函式

2. 簡述:不用繼承的方式為一個類增加成員方法。 3. 實現程式碼: /// <summary> /// Component擴充套件類 /// </summary> internal static class ComponentDesignMod

C++函式類用法詳解

在C++中,我們使用類對資料進行了隱藏和封裝,類的資料成員一般都定義為私有成員,成員函式一般都定義為公有的,以此提供類與外界的通訊介面。但是,有時需要定義一些函式,這些函式不是類的一部分,但又需要頻繁地訪問類的資料成員,這時可以將這些函式定義為該函式的友元函式。除了友元函式

c++函式宣告及其呼叫

1.友元函式的簡單介紹 1.1為什麼要使用友元函式 在實現類之間資料共享時,減少系統開銷,提高效率。如果類A中的函式要訪問類B中的成員(例如:智慧指標類的實現),那麼類A中該函式要是類B的友元函式。具體來說:為了 使其他類的成員函式直接訪問該類的私有變數。即:允許外

c++函式說明

1)C++中引入友元函式,是為在該類中提供一個對外(除了他自己以外)訪問的視窗;2)這個友元函式他不屬於該類的成員函式,他是定義在類外的普通函式  只是在類中宣告該函式可以直接訪問類中的private或者protected成員。使用友元函式注意的要點:類中通過使用關鍵字fri

試圖對C++函式,靜態成員函式做個小結

2014年12月13日 22:28:43第一篇部落格   以下僅僅是個人觀點,請大家指正.  友元函式分類:(按照我的想法,結合C++ Plus) 一.   1. 讓其他類(B類)的成員數最為類A的友元函式(只需要在類A中宣告即可)         2.讓類B成為類A的友元

c++函式類的理解

1,友元函式的定義和作用 我們已知道類具有封裝和資訊隱藏的特性。只有類的成員函式才能訪問類的私有成員,程式中的其他函式是無法訪問私有成員的。非成員函式可以訪問類中的公有成員,但是如果將資料成員都定義為公有的,這又破壞了隱藏的特性。另外,應該看到在某些情況下,特別是在對某

C++ 函式/實際使用的一些注意事項/重複定義

友元函式可以分成1.外部函式 2.其他類函式成員作為友元函式 其他的諸如友元函式導致資訊不安全的老梗就不多說了,簡單說說今天遇到的問題 重複定義問題,出現在 其他類成員作為友元函式的時候 (1). 在A類的宣告中寫下函式 (2). 在A類外給出具體定義

C++函式訪問類的私有成員

#include <iostream>#include<cstring>using namespace std ;class Student{private:string  name;int age;int sore;public:Student(string name,int age

過載輸入輸出運算子引用的理解

#include <iostream.h> class coord{ int x,y; public: coord(int i=0,int j=0) { x=i; y=j; } friend ostream& operator<&

c++ 函式,模板函式

友元函式. 類的友元函式是定義在類外部,但有權訪問類的所有私有(private)成員和保護(protected)成員。儘管友元函式的原型有在類的定義中出現過,但是友元函式並不是成員函式。 友元可以是一個函式,該函式被稱為友元函式;友元也可以是一個類,該類被稱

C++ 函式

#include <iostream> using namespace std; class girl { private: char *name; int age; friend class boy; //宣告類boy是類girl的友元 public:

c++函式簡析

在實現類之間資料共享時,減少系統開銷,提高效率。如果類A中的函式要訪問類B中的成員(例如:智慧指標類的實現),那麼類A中該函式要是類B的友元函式。具體來說:為了 使其他類的成員函式直接訪問該類的私有變數。即:允許外面的類或函式去訪問類的私有變數和保護變數,從而使兩個類共享同一函式。 3.友元函式和普通

C++函式類(C++ friend)詳解

私有成員只能在類的成員函式內部訪問,如果想在別處訪問物件的私有成員,只能通過類提供的介面(成員函式)間接地進行。這固然能夠帶來資料