When should you use 'friend' in C++?

前端 未结 30 1628
孤街浪徒
孤街浪徒 2020-11-22 10:12

I have been reading through the C++ FAQ and was curious about the friend declaration. I personally have never used it, however I am interested in exploring the language.

30条回答
  •  盖世英雄少女心
    2020-11-22 10:45

    This may not be an actual use case situation but may help to illustrate the use of friend between classes.

    The ClubHouse

    class ClubHouse {
    public:
        friend class VIPMember; // VIP Members Have Full Access To Class
    private:
        unsigned nonMembers_;
        unsigned paidMembers_;
        unsigned vipMembers;
    
        std::vector members_;
    public:
        ClubHouse() : nonMembers_(0), paidMembers_(0), vipMembers(0) {}
    
        addMember( const Member& member ) { // ...code }   
        void updateMembership( unsigned memberID, Member::MembershipType type ) { // ...code }
        Amenity getAmenity( unsigned memberID ) { // ...code }
    
    protected:
        void joinVIPEvent( unsigned memberID ) { // ...code }
    
    }; // ClubHouse
    

    The Members Class's

    class Member {
    public:
        enum MemberShipType {
            NON_MEMBER_PAID_EVENT,   // Single Event Paid (At Door)
            PAID_MEMBERSHIP,         // Monthly - Yearly Subscription
            VIP_MEMBERSHIP,          // Highest Possible Membership
        }; // MemberShipType
    
    protected:
        MemberShipType type_;
        unsigned id_;
        Amenity amenity_;
    public:
        Member( unsigned id, MemberShipType type ) : id_(id), type_(type) {}
        virtual ~Member(){}
        unsigned getId() const { return id_; }
        MemberShipType getType() const { return type_; }
        virtual void getAmenityFromClubHouse() = 0       
    };
    
    class NonMember : public Member {
    public:
       explicit NonMember( unsigned id ) : Member( id, MemberShipType::NON_MEMBER_PAID_EVENT ) {}   
    
       void getAmenityFromClubHouse() override {
           Amenity = ClubHouse::getAmenity( this->id_ );
        }
    };
    
    class PaidMember : public Member {
    public:
        explicit PaidMember( unsigned id ) : Member( id, MemberShipType::PAID_MEMBERSHIP ) {}
    
        void getAmenityFromClubHouse() override {
           Amenity = ClubHouse::getAmenity( this->id_ );
        }
    };
    
    class VIPMember : public Member {
    public:
        friend class ClubHouse;
    public:
        explicit VIPMember( unsigned id ) : Member( id, MemberShipType::VIP_MEMBERSHIP ) {}
    
        void getAmenityFromClubHouse() override {
           Amenity = ClubHouse::getAmenity( this->id_ );
        }
    
        void attendVIPEvent() {
            ClubHouse::joinVIPEvent( this->id );
        }
    };
    

    Amenities

    class Amenity{};
    

    If you look at the relationship of these classes here; the ClubHouse holds a variety of different types of memberships and membership access. The Members are all derived from a super or base class since they all share an ID and an enumerated type that are common and outside classes can access their IDs and Types through access functions that are found in the base class.

    However through this kind of hierarchy of the Members and its Derived classes and their relationship with the ClubHouse class the only one of the derived class's that has "special privileges" is the VIPMember class. The base class and the other 2 derived classes can not access the ClubHouse's joinVIPEvent() method, yet the VIP Member class has that privilege as if it has complete access to that event.

    So with the VIPMember and the ClubHouse it is a two way street of access where the other Member Classes are limited.

提交回复
热议问题