zoukankan      html  css  js  c++  java
  • C++友元

    友元说明

    相对于其他的编程语言,“友元”是C++中特别的一种语法。那它有什么作用呢?
    其实“友元”就是提供一种访问类私有部分的的方法。如果没有“友元”,我们只能通过类本身提供的公有方法来访问,但相对地,这样限制太高了,所以“友元”就是一种的在类的封装性和实用性中很好的“折中”方式。

    C++中的友元有三种:

    • 友元函数
    • 友元类
    • 友元成员函数

    C++中使用关键字friend来定义。

    友元函数

    这里直接用代码来说明:

    #include <iostream>
    #include <string>
    
    class Person {
    private:
        std::string account;
        std::string passwd;
    
    public:
        Person(std::string ac, std::string pw);
    
        // 这里使用friend关键字,指定Point中的getPerson方法可以使用Person类的私有变量。
        friend void getPerson(Person &p);
    };
    
    Person::Person(std::string ac, std::string pw) {
        account = ac;
        passwd = pw;
    }
    
    
    void getPerson(Person &p) {
        // 因为定义了友元,这里就可以访问Person类的私有变量了。
        std::cout << "account: " << p.account
                  << ", passwd: " << p.passwd << std::endl;
    }
    
    int main() {
        Person p("xingyys", "123456");
    
        getPerson(p);
    
        return 0;
    }
    

    这个例子还是比较简单的,只要在指定的方法中添加关键字就可以实现了。

    友元类

    在来一个例子说明:

    #include <iostream>
    #include <string>
    
    class Tv {
    private:
        int state;
        int volume;
        int maxchannel;
        int channel;
        int mode;
        int input;
    
    public:
        // 在这里指定谁是他的友元
        friend class Remote;
    
        enum {
            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(2), 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;
    
    };
    
    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(); }
    };
    
    bool Tv::volup() {
        if (volume < MaxVal) {
            volume++;
            return true;
        } else {
            return false;
        }
    }
    
    bool Tv::voldown() {
        if (volume > MinVal) {
            volume--;
            return true;
        } else {
            return false;
        }
    }
    
    void Tv::chanup() {
        if (channel < maxchannel)
            channel++;
        else
            channel = 1;
    }
    
    void Tv::chandown() {
        if (channel > 1)
            channel--;
        else
            channel = maxchannel;
    }
    
    void Tv::settings() const {
        using std::cout;
        using std::endl;
        cout << "TV is " << (state == Off ? "Off" : "On") << endl;
        if (state == On) {
            cout << "Volume setting = " << volume << endl;
            cout << "Channel setting = " << channel << endl;
            cout << "Mode = "
                 << (mode == Antenna ? "antenna" : "cable") << endl;
            cout << "Input = "
                 << (input == TV ? "TV" : "DVD") << endl;
        }
    }
    
    int main() {
        using std::cout;
        Tv s42;
        cout << "Initial setting for 42" TV:
    ";
        s42.settings();
        s42.onoff();
        s42.chanup();
        cout << "
    Adjusted setting for 42" TV:
    ";
        s42.chanup();
        cout << "
    Adjusted settings for 42" TV:
    ";
        s42.settings();
    
        Remote grey;
    
        grey.set_chan(s42, 10);
        grey.volup(s42);
        grey.volup(s42);
        cout << "
    42" setting after using remote:
    ";
        s42.settings();
    
        Tv s58(Tv::On);
        s58.set_mode();
        grey.set_chan(s58, 28);
        cout << "
    58" settings:
    ";
        s58.settings();
        return 0;
    }
    

    友元成员函数

    #include <iostream>
    #include <string>
    
    class Person;
    
    class Point {
    public:
        void getPerson(Person &p);
    };
    
    class Person {
    private:
        std::string account;
        std::string passwd;
    
    public:
        Person(std::string ac, std::string pw);
    
        // 这里使用friend关键字,指定Point中的getPerson方法可以使用Person类的私有变量。
        friend void Point::getPerson(Person &p);
    };
    
    Person::Person(std::string ac, std::string pw) {
        account = ac;
        passwd = pw;
    }
    
    
    void Point::getPerson(Person &p) {
        // 因为定义了友元,这里就可以访问Person类的私有变量了。
        std::cout << "account: " << p.account
                  << ", passwd: " << p.passwd << std::endl;
    }
    
    int main() {
        Person p ("xingyys", "123456");
    
        Point pt;
    
        pt.getPerson(p);
    
        return 0;
    }
    

    补充

    • 不能定义类的对象。
    • 可以用于定义指向这个类型的指针或引用。
    • 用于声明(不是定义),使用该类型作为形参类型或者函数的返回值类型。
    • 友元关系不能被继承。
    • 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
    • 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明
  • 相关阅读:
    [51nod] 1088 最长回文子串 #Hash+二分
    [51nod] 1378 夹克老爷的愤怒 #树形DP
    [BZOJ] 2456: mode #众数计数法
    [51nod] 1199 Money out of Thin Air #线段树+DFS序
    [51nod] 1494 选举拉票 #算法设计策略
    [51nod] 1463 找朋友 #离线+扫描线
    [BZOJ] 2733: [HNOI2012]永无乡 #线段树合并+并查集
    [BZOJ] 1012: [JSOI2008]最大数maxnumber
    [Codeforces] E. Lomsat gelral #DSU on Tree
    [BZOJ] 4756: [Usaco2017 Jan]Promotion Counting #线段树合并+权值线段树
  • 原文地址:https://www.cnblogs.com/xingyys/p/10848515.html
Copyright © 2011-2022 走看看