1. 程式人生 > >芝麻軟體工作室的專欄

芝麻軟體工作室的專欄

在面向物件的程式設計中,類的封裝性使得我們使用類(物件)的成員資料時經常要通過類(物件)的成員函式。這對於類是一種保護。但在某些情況下,頻繁的成員函式呼叫使得效率嚴重受損。

例如,定義矩陣類,並有兩個矩陣物件相乘,為了獲得矩陣中的元素值(私有成員),要頻繁呼叫取值函式(公有成員)。

怎樣可以提高效率?——使用友元函式。在C++中友元(friend)函式允許在類外訪問該類中的任何成員,就象類的成員函式一樣。

友元函式用關鍵字friend說明。下面用友元函式過載運算子“+”,以實現c=d+c。(即實數與複數的加法。)

◆ 1、定義友元函式的一般格式:
首先,在類聲明裡宣告:
class Complex
{
     ……
    friend Complex operator + (double,Complex);
}; 
/*opration+為類Complex類的友元函式, friend只用於類說明中 ……*/
第二步,在類外定義:
Complex operator + (double d , Complex c)
{
    return Complex(d+c.Real , c.Image) ;
}

//注意友元不是成員函式,在類宣告以外的地方也不加friend
第三步,使用,友元函式可以在任何地方直接訪問類的私有成員
void main(void)
{
    …… c=d+c1;
}

這裡d+c1被C++編譯器解釋為operator+(d,c1),即呼叫友元函式operator+(d,c1)。

◆ 2、再進一步,如果使用友元函式

friend complex operator +(complex c1 , complexc2) ;
無論是複數與複數相加,還是實數與複數相加(不論實數在前還是在後)都可以用。為什麼呢?

因為有此例所定義的預設的建構函式,實數會被強制轉換為虛部為零的複數。d+c1被解釋為:
operator+(complex(d) , c1)

◆ 3、
friend Complex operator+(const Complex & c1,const Complex & c2)
{
       ……
}


這裡採用Complex物件的引用而不是物件本身,呼叫時不再重新分配記憶體建立一個複製的物件,函式效率會更高。加const,實參只讀,可防止實參被修改。


◆ 4、單目運算子前置“++”的友元函式過載方式如下:
Complex Complex::operator++(Complex & c )
{
       return (++c.Real , ++c.Image) ;
}

採用友元函式方式定義與使用都很方便。但採用友元方式必須使用引用,因為被施加“++”運算的是一個引數。

◆ 5、友元函式過載後置“++”如下:
friend Complex operator++(Complex & c , int)
{
       Complex temp=c;
       c.Real++ , c.Image++ ;
       return temp;
}

採用引用型別,實參c做了++,而temp是++前的值。

◆ 6、友元函式注意點:
  • 友元函式不是類的成員函式,在友元函式體中訪問物件的成員,必須用物件名加運算子“.”加物件成員名。這一點和一般函式一樣。但友元函式可以訪問類中的所有成員(公有的、私有的、保護的),一般函式只能訪問類中的公有成員;
  • 友元函式不受類中的訪問許可權關鍵字限制,可以把它放在類的公有、私有、保護部分,但結果一樣;
  • 某類的友元函式的作用域並非該類域。如果該友元函式是另一類的成員函式,則其作用域為另一類的類域,否則與一般函式相同。
  • 友元函式破壞了面向物件程式設計類的封裝性,所以友元函式如不是必須使用,則儘可能少用。或者用其他手段保證封裝性。
    友元還有友元類概念,整個類可以是另一個類的友元。友元類的每個成員函式都是另一個類的友元函式,都可訪問另一個類中的保護或私有資料成員。定義方法如下:
    class A
    {
        ……
        friend class B; //B為A的友元類
        ……
    };