亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++中的friend函數詳細解析

2020-01-26 14:23:52
字體:
來源:轉載
供稿:網友

為什么要使用友元函數

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

實際上具體大概有下面兩種情況需要使用友元函數:(1)運算符重載的某些場合需要使用友元。(2)兩個類要共享數據的時候。

使用友元函數的優缺點

優點:能夠提高效率,表達簡單、清晰。

缺點:友元函數破環了封裝機制,盡量不使用成員函數,除非不得已的情況下才使用友元函數。

C++中的友元機制允許類的非公有成員被一個類或者函數訪問,友元按類型分為三種:普通非類成員函數作為友元,類的成員函數作為友元,類作為友元。友元包括友元的聲明以及友元的定義。友元的聲明默認為了extern,就是說友元類或者友元函數的作用域已經擴展到了包含該類定義的作用域,所以即便我們在類的內部定義友元函數也是沒有關系的。

友元可以是一個函數,該函數被稱為友元函數;友元也可以是一個類,該類被稱為友元類。友元函數的特點是能夠訪問類中的私有成員的非成員函數。友元函數從語法上看,它與普通函數一樣,即在定義上和調用上與普通函數一樣。

友元函數的實現可以在類外定義,但必須在類內部聲明

友元函數是可以直接訪問類的私有成員的非成員函數。它是定義在類外的普通函數,它不屬于任何類,

但需要在類的定義中加以聲明,聲明時只需在友元的名稱前加上關鍵字friend。

我們已知道類具有封裝和信息隱藏的特性。只有類的成員函數才能訪問類的私有成員,程序中的其他函數是無法訪問私有成員的。非成員函數可以訪問類中的公有成員,但是如果將數據成員都定義為公有的,這又破壞了隱藏的特性。另外,應該看到在某些情況下,特別是在對某些成員函數多次調用時,由于參數傳遞,類型檢查和安全性檢查等都需要時間開銷,而影響程序的運行效率。

為了解決上述問題,提出一種使用友元的方案。友元是一種定義在類外部的普通函數,但它需要在類體內進行說明,為了與該類的成員函數加以區別,在說明時前面加以關鍵字friend。友元不是成員函數,但是它可以訪問類中的私有成員。友元的作用在于提高程序的運行效率(即減少了類型檢查和安全性檢查等都需要的時間開銷),但是,它破壞了類的封裝性和隱藏性,使得非成員函數可以訪問類的私有成員。

1.普通的非成員函數友元

#include "cmath" #include "iostream" using namespace std; class Point { public:    Point(double xx,double yy)    {      x=xx;      y=yy;    }    void GetXY();    friend double Distance(Point &a,Point &b); protected: private:    double x,y; }; void Point::GetXY() {    //cout<<"("<<this->x<<","<<this->y<<")"<<endl;    cout<<"("<<x<<","<<y<<")"<<endl; } double Distance(Point &a,Point &b) {    double length;    length=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));   //它可以引用類中的私有成員    return length; } int main(void) {    Point p1(3.0,4.0),p2(6.0,8.0);    p1.GetXY();  //成員函數的調用方法,通過使用對象來調用    p2.GetXY();    double d = Distance(p1,p2);   //友元函數的調用方法,同普通函數的調用一樣,不要像成員函數那樣調用    cout<<d<<endl;    system("pause");    return 0; } 

說明:在該程序中的Point類中說明了一個友元函數Distance(),它在說明時前邊加friend關鍵字,標識它不是成員函數,而是友元函數。它的定義方法與普通函數定義一樣,而不同于成員函數的定義,因為它不需要指出所屬的類。但是,它可以引用類中的私有成員,函數體中的a.x,b.x,a.y,b.y都是類的私有成員,它們是通過對象引用的。在調用友元函數時,也是同普通函數的調用一樣,不要像成員函數那樣調用。本例中,p1.Getxy()和p2.Getxy()這是成員函數的調用,要用對象來表示。而Distance(p1, p2)是友元函數的調用,它直接調用,不需要對象表示,它的參數是對象。(該程序的功能是已知兩點坐標,求出兩點的距離。)

下面對上面的代碼進行輸入、輸出流的重載:

#include <cmath> #include <iostream> using namespace std; class Point { public:    Point(double xx,double yy)    {       x=xx;       y=yy;    }    void GetXY();    friend double Distance(Point &a,Point &b);    friend ostream &operator <<(ostream &a,Point &b); protected: private:    double x,y; }; // friend ostream& operator<<(ostream& o,A& another); ostream &operator <<(ostream &out,Point &b)  //在類中聲明的時候,可以是ostream &a,函數定義的時候也可以是ostream &out {    out<<"("<<b.x<<","<<b.y<<")"<<endl;    return out; } void Point::GetXY() {    //cout<<"("<<this->x<<","<<this->y<<")"<<endl;    //cout<<"("<<x<<","<<y<<")"<<endl;    cout<<*this; } double Distance(Point &a,Point &b) {    double length;    length=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));    return length; } int main(void) {    Point p1(3.0,4.0),p2(6.0,8.0);    p1.GetXY();    p2.GetXY();    double d = Distance(p1,p2);    cout<<d<<endl;    system("pause");    return 0;  } 

2.類作為友元

類作為友元需要注意的是友元類和原始類之間的相互依賴關系,如果在友元類中定義的函數使用到了原始類的私有變量,那么就需要在友元類定義的文件中包含原始類定義的頭文件。但是在原始類的定義中(包含友元類聲明的那個類),就不需要包含友元類的頭文件.

另外,不需要在類定義前去聲明友元類,因為友元類的聲明自身就是一種聲明。

//A.h  #pragma once  #include <iostream>  using namespace std;  class A  {    //friend class B; //如果不寫這句話將會出現編譯錯誤 public:    ~A(void);    A(); private:     int m_nItem; };  //A.cpp #include "A.h"  A::A() {   m_nItem =3; }  A::~A(void) { } //B.h #pragma once   class B  {  public:    B(void);    ~B(void);    int func();  };  //B.cpp #include "StdAfx.h"  #include "B.h"  #include "A.h" //must include A.h  #include <iostream>   B::B(void) { }  B::~B(void) { }  int B::func()  {    cout<<"This is in B"<<endl;    A a;   return a.m_nItem; }  

3.類成員函數作為友元函數

這個稍微有點復雜,因為你要類成員函數作為友元,你在聲明友元的時候要用類限定符,所以必須先定義包含友元函數的類,但是在定義友元的函數時候,又必須事先定義原始類。通常的做法先定義包含友元函數的類,再定義原始類,這個順序不能亂。(如果是友元類,則沒有這種這種必須)如下面所示:

//A.h #pragma once #include "B.h" class A { friend int B::func(A xx); public:   A(void):mx(20),my(30){}   ~A(void){} private:   int mx;   int my; }; //B.h #pragma once class A; class B { public:   B(void);   ~B(void);   int func(A xx); }; //B.cpp #include "B.h" #include "A.h"  B::B(void) { } B::~B(void) { } int B::func(A xx) {   return xx.mx * xx.my; } //main.cpp #include "A.h" #include "B.h" #include <iostream> using namespace std; void main() {   A a;   B b;   cout<<b.func(a)<<endl;   system("pause"); } 

4. 友元不具有相互性,只具有單項性

若類B是類A的友元,類A不一定是類B的友元,要看在類中是否有相應的聲明。

5. 友元不能被繼承

B是A的友元類,C是B的子類,推不出C是A的友元

6. 友元不具有傳遞性

B是A的友元,C是B的友元,推不出C是A的友元

7. 友元函數的使用技巧

在用C++實現單例模式時,可以利用友元函數實例化對象。然后把類的構造函數和析構函數都設計成私有函數。

class CMySingleton { public:   friend CMySingleton& InstanceMEC();  private:   CMySingleton() {};   CMySingleton(const CMySingleton &lxSington) {};   ~CMySingleton(){}; };  CMySingleton& InstanceMEC() {   //因為函數InstanceMEC()是類ClxSingletonMEC的友元函數,所以可以訪問類所有的成員函數.所以不會有編譯錯誤   static CMySingleton Instance;    return Instance; }  

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产成人精品久久二区二区| 国产精品日韩在线观看| 亚洲999一在线观看www| 午夜精品一区二区三区视频免费看| 亚洲变态欧美另类捆绑| 91精品久久久久| 日韩精品在线观看一区| 亚洲视频欧美视频| www亚洲欧美| 欧美xxxx14xxxxx性爽| 丝袜亚洲另类欧美重口| 久久久亚洲福利精品午夜| 一个色综合导航| 亚洲精品美女免费| 亚洲天堂第一页| 久久夜色精品国产亚洲aⅴ| 高跟丝袜一区二区三区| 久久久97精品| 中文字幕精品视频| 庆余年2免费日韩剧观看大牛| 在线观看不卡av| 亚洲男人的天堂网站| 欧美午夜无遮挡| 一个人看的www久久| 久久精品亚洲一区| 欧美视频中文在线看| 欧美有码在线观看视频| 高清欧美一区二区三区| 亚洲精品电影久久久| 日韩经典中文字幕| 亚洲有声小说3d| 日韩精品久久久久| 欧美激情在线狂野欧美精品| 91禁外国网站| 国产精品丝袜久久久久久高清| 庆余年2免费日韩剧观看大牛| 精品一区电影国产| 欧美人在线观看| 成人日韩av在线| 国产午夜精品一区二区三区| 日韩av一区在线| 国产欧美精品日韩精品| 久久久免费电影| 伊人久久久久久久久久久| 欧美日韩国产综合新一区| 亚洲伊人久久大香线蕉av| 69av在线播放| 日韩中文字幕网址| 国内免费精品永久在线视频| 亚洲va欧美va国产综合剧情| 亚洲精选一区二区| 日韩av不卡电影| 国产精品极品尤物在线观看| 日韩一区视频在线| 精品国产福利视频| 久久黄色av网站| 九九热这里只有精品6| 亚洲高清在线观看| 国产精品久久久久久婷婷天堂| 久久天天躁狠狠躁夜夜躁| 日韩精品极品视频免费观看| 韩日精品中文字幕| 国产精品激情自拍| 情事1991在线| 欧美日产国产成人免费图片| 国产精品第一视频| 久久精品夜夜夜夜夜久久| 91av在线不卡| 国产精品视频久久久久| 国产亚洲精品综合一区91| 在线成人激情视频| 国产一区二区三区在线观看视频| 久久久久久久久久久国产| 日韩美女免费观看| 成人做爰www免费看视频网站| 91在线免费视频| 亚洲精品第一页| 69av在线视频| 欧美性理论片在线观看片免费| 亚洲第五色综合网| 日韩欧美极品在线观看| 久久6免费高清热精品| 在线观看国产精品日韩av| 欧美在线视频免费观看| 91精品视频一区| 亚洲一区二区三区久久| 国产精品久久久久久婷婷天堂| 国产精品国内视频| 亚洲国产精品系列| 日韩成人av网址| 欧美精品做受xxx性少妇| 亚洲最新av网址| 精品视频久久久久久久| 亚洲影视九九影院在线观看| 国产精品免费视频久久久| 亚洲免费成人av电影| 亚洲电影av在线| 欧美专区在线视频| 欧美高清性猛交| 精品国产一区二区三区在线观看| 久久久免费观看| 日韩精品免费综合视频在线播放| 欧美激情亚洲另类| 中文在线资源观看视频网站免费不卡| 日本欧美黄网站| 久久久久五月天| 久久人人爽人人爽人人片av高清| 久久久久国色av免费观看性色| 亚洲精品大尺度| 国产美女精品视频| 日韩视频永久免费观看| 国产精品成人观看视频国产奇米| 欧美午夜影院在线视频| 国产69久久精品成人看| 日韩在线视频线视频免费网站| 欧美另类99xxxxx| 91精品久久久久久久久久久久久| 欧美一级大胆视频| 91高清视频免费观看| 亚洲第一区中文字幕| 一区二区三区久久精品| 久久精品国产视频| 中文字幕亚洲激情| 亚洲日本中文字幕| 久久亚洲成人精品| 成人免费观看网址| 精品亚洲一区二区三区| 国产亚洲精品成人av久久ww| 欧美电影免费观看高清完整| 日韩欧美国产黄色| 国模精品视频一区二区| 欧美午夜激情在线| 国产丝袜视频一区| 亚洲欧洲高清在线| 亚洲国产精品成人va在线观看| 欧美大片在线看免费观看| 午夜精品一区二区三区在线视频| 国产人妖伪娘一区91| 日韩毛片中文字幕| 狠狠躁18三区二区一区| 欧美精品激情blacked18| 九色91av视频| 国产精品夜间视频香蕉| 国产日韩欧美在线观看| 亚洲国产日韩欧美在线图片| 国产精品男人的天堂| 国产69久久精品成人看| 欧美巨乳美女视频| 91亚洲国产成人精品性色| 国产91色在线|免| 国产在线观看一区二区三区| 国产成人综合精品| 欧美黑人国产人伦爽爽爽| 欧美放荡办公室videos4k| 国外色69视频在线观看| 欧美日韩裸体免费视频| 日韩免费在线播放| 国产一区二区日韩精品欧美精品| 国内精品模特av私拍在线观看| 成人黄色网免费| 国产精品午夜国产小视频| 欧美在线视频一区| 亚洲一区二区在线| 亚洲成人网久久久|