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

前端 未结 30 2116
孤街浪徒
孤街浪徒 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:53

    The friend keyword has a number of good uses. Here are the two uses immediately visible to me:

    Friend Definition

    Friend definition allows to define a function in class-scope, but the function will not be defined as a member function, but as a free function of the enclosing namespace, and won't be visible normally except for argument dependent lookup. That makes it especially useful for operator overloading:

    namespace utils {
        class f {
        private:
            typedef int int_type;
            int_type value;
    
        public:
            // let's assume it doesn't only need .value, but some
            // internal stuff.
            friend f operator+(f const& a, f const& b) {
                // name resolution finds names in class-scope. 
                // int_type is visible here.
                return f(a.value + b.value);
            }
    
            int getValue() const { return value; }
        };
    }
    
    int main() {
        utils::f a, b;
        std::cout << (a + b).getValue(); // valid
    }
    

    Private CRTP Base Class

    Sometimes, you find the need that a policy needs access to the derived class:

    // possible policy used for flexible-class.
    template
    struct Policy {
        void doSomething() {
            // casting this to Derived* requires us to see that we are a 
            // base-class of Derived.
            some_type const& t = static_cast(this)->getSomething();
        }
    };
    
    // note, derived privately
    template class SomePolicy>
    struct FlexibleClass : private SomePolicy {
        // we derive privately, so the base-class wouldn't notice that, 
        // (even though it's the base itself!), so we need a friend declaration
        // to make the base a friend of us.
        friend class SomePolicy;
    
        void doStuff() {
             // calls doSomething of the policy
             this->doSomething();
        }
    
        // will return useful information
        some_type getSomething();
    };
    

    You will find a non-contrived example for that in this answer. Another code using that is in this answer. The CRTP base casts its this pointer, to be able to access data-fields of the derived class using data-member-pointers.

提交回复
热议问题