c++友元

c++友元

参考《c++ Primer Plus》 第6版15.1ios

C++控制对类对象私有部分的访问,在外部没法直接访问类的私有或保护成员。一般,公有类方法提供惟一的访问途径。有时这种限制太严格,不适合特定的编程问题。因此C++提供了友元这种形式,经过让函数或类成为类的友元,能够赋予该函数或类与类的成员函数具备相同的访问权限。c++

友元的做用在于提升程序的运行效率(即减小了类型检查和安全性检查等都须要的时间开销),可是,它破坏了类的封装性和隐藏性,使得非成员函数能够访问类的私有成员。编程

友元有3种:

(1)友元函数安全

(2)友元类函数

(3)友元成员函数this

 

1.友元函数

在类定义体中由关键字friend加以修饰说明的非成员函数spa

#include <iostream>
using namespace std;
class Window
{
        public: Window(int x, int y, int h, int w)
                {   
                        X=x, Y=y, H=h, W=w;
                }   
                friend long Area(Window & WinObj); //在类中声明出友员函数的原型
                int getH() 
                {   
                        return H;
                }   
                int getW()
                { return W;
                }   
        private: int X,Y,H,W;
};
long Area(Window & WinObj) //在类外定义出友员函数的函数体
{ 
        return (long)WinObj.H*WinObj.W;
}

//实现经过对象访问类中的private成员,由于对窗口的面积的计算最简单的方式应该是H*W。
int main()
{ 
        Window winA(10,10,300,300);
        cout <<"Window Area is "<< endl;
        cout <<"Window Area square: "<< Area(winA)<< endl;
        return 0;
}

运行结果:设计

Window Area is 
Window Area square: 90000

友员函数与成员函数在编程方面的不一样点:
  ① 友员函数在类体内应该采用friend加以限定,但成员函数不须要。
  ② 友员函数体在类体外不须要采用"类名::"加以限定。
  ③ 调用它时不须要采用"对象名.成员名"方式,而是直接调用它。
  ④ 因为友员函数不是成员函数,于是无this指针,在函数体中访问对象中的成员时必须经过对象名(可将形参定义为引用),而在成员函数体内能够直接访问成员数据。指针

注释:code

类的友元函数是非成员函数,其访问权限与成员函数相同。

 

2. 友元类

能够将类做为友元,友元类的全部方法均可以访问原始类的私有成员和保护成员。

以下 friend class Remote; 声明Remote为Tv类的友元类:

//tv.h -- Tv and Remote classes
#ifndef TV_H_
#define TV_H_
class Tv
{
    public:
        friend class Remote; //Remote can access Tv private parts
        enum State{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(12),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
    private:
        int state;
        int volume;
        int maxchannel;
        int channel;
        int mode;
        int input;
};
class Remote
{
    private:
        int mode;
    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();}
};

 

3. 友元成员函数

在Remote类中,只有set_channel(Tv & tv, int ch)方法直接访问Tv类的私有成员,因此能够选择只让这个方法成为类的友元,而没必要让Remote整个类成为友元。不过这么作必须当心排列各类声明和定义的顺序。

让Remote::set_channel()成为Tv类的友元方法是,在Tv类中将其声明为友元:

//tvfm.h
#ifndef TVFM_H_
#define TVFM_H_
class Tv;
class Remote
{
    public:
        enum State{Off,on};
        enum {MinVal,MaxVal=20};
        enum {Antenna,Cable};
        enum {TV,DVD};
    private:
        int mode;
    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_mode(Tv & t);
        void set_input(Tv & t);
        void set_chan(Tv & t,int c);
};
class Tv
{
    public:
        friend void Remote::set_chan(Tv & t,int c);
        enum State{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(12),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
    private:
        int state;
        int volume;
        int maxchannel;
        int channel;
        int mode;
        int input;
};
//Remote methods as inline functions
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_mode(Tv & t){t.set_mode();}
inline void Remote::set_input(Tv & t){t.set_input();}
inline void Remote::set_chan(Tv & t,int c) {t.channel=c;}
#endif

 

为何须要友员函数

  ① 在封装和快速性两方面合理选择----OOP中类的主要优势是能够实现数据隐藏与保护,即不容许非成员函数对它访问,这样能够提升数据使用的安全性。但在访问数据的效率方面则降低(由于正常时应该经过public型的方法来访问)。但在某些应用场合下,非成员函数体中须要经过对象名直接访问类中的private成员,以达到高速高效率地访问数据,这能够经过友员函数来实现。
 
  ② 有些函数须要放在类的外面或者类设计完之后再加以补充的,此时可能不能设计为类中的成员函数,可是又须要访问类中的私有成员。

相关文章
相关标签/搜索