What's the difference between friendship and i

2019-02-07 12:23发布

Suppose there are two classes A and B:

class A {};
class B {};

In what aspects differ the two examples below?

Example 1:

class C : public A, public B {}; 

Example 2:

class C
{
    //private
    friend class A;
    friend class B;
}

4条回答
beautiful°
2楼-- · 2019-02-07 12:59

While the answers you've gotten are reasonably accurate, I don't think they're really complete. In particular, although they explain what the difference between friendship and inheritance is, they don't really explain much about which you should use when, or how the difference affects your code.

The primary use of inheritance (in C++) is to define an interface in a base class, and implement that interface in each of a number of derived classes. The parts of the interface that a derived class must implement will normally be signified by pure virtual functions in the base class.

The primary use of friendship in C++ is to define something that forms part of an interface, but for syntactical reasons can't be a member function. One extremely common example is a stream insertion or extraction operator. To implement these as member functions, they'd have to be members of the stream class. Since we don't want to modify the stream class constantly, they're instead free functions that take a reference to a stream as their left parameter, and a reference to a (possibly const) object of the type they insert/extract as their right operand.

These don't necessarily have to be friends of the class--they can be written to use only the class' public interface. If you do that, though, it generally means the class is exposing more in its public interface than is otherwise necessary. The interface is no longer minimal, which tends to indicate a problematic design.

One note though: you can define a friend function inside a class definition:

class Foo { 
// ...
    friend std::ostream &operator<<(std::ostream &os, Foo const &f) { 
        // ...
    }
};

At first this may seem strange (and syntactically it is, somewhat). Even though it's defined inside the class definition, the friend means that this is not a member function. At least in my opinion, this reflects its situation fairly accurately: conceptually, it's part of the class. It has access to private members, just like any other member of the class. The fact that it's a free function rather than a member function is purely an implementation artifact that has essentially nothing to do with the code's design.

That also points to another difference between friendship and inheritance: with inheritance, you're normally dealing primarily with member functions. Each member function still receives a this pointer, so each member function is directly associated with a specific instance of the class. Yes, you can define it to also receive (a pointer or reference to) another instance of the class if desired, but it always receives this, regardless. A friend (function or class) doesn't get this--the friend declaration just means that the names that are private to that other class are visible to the friend. To get access to an actual instance of that class, you typically need to pass it as a parameter, or something on that order.

Finally, I'll note that the preceding sort of ignores the possibilities of private or protected inheritance. Private inheritance normally means that the derived class is implemented in terms of the base class. This can be handy if (for example) the derived class is similar to the base class, but isn't related in the design--i.e., you're not asserting that an instance of the derived class can be used anywhere an instance of the base class was needed. Its use of the base class is an implementation detail that the rest of the world doesn't need to know or care about.

Protected inheritance is pretty much a mistake. It's allowed because it's consistent with public, private and protected members (which do make sense) but for inheritance, protected simply doesn't seem to accomplish anything useful.

查看更多
Emotional °昔
3楼-- · 2019-02-07 13:05

In the context you're using, to answer your question to the best of my ability, friends simply allow your classes to share protected/private data, while inheritance will do the same, except there'll be a deeper relationship, where the classes are one in the same (such as with casting).

查看更多
可以哭但决不认输i
4楼-- · 2019-02-07 13:09

A friend can touch the private parts (pun only slightly intentional! ;) ) of whatever it is friend of, but nothing of A and B are part of C - it just means that "A and B can touch C's private bits"). Anything "less" than private is of course also available to A and B, so if C has protected or public members, that will also be available.

When you inherit, the A and B becomes part of C. Any private sections of A and B are not available to C. In the "is-a" vs. "has-a" nomenclature, C now is-a A and is-a B - in other words, it's inherited from A, so it "behaves like A from an interface perspective.

查看更多
We Are One
5楼-- · 2019-02-07 13:17

There are several big differences. Inheritance and friendship are very different.

With friendship, class C is NOT an instance of class A or class B. Therefore, if you have a function like:

void processMyClass(A* a);

you cannot pass it an instance of C whereas, if C subclasses A (publicly), it IS an instance of A.

With friendship, class A and B can touch all the private member data and functions of C. With inheritance, class C can touch the public and protected members of A and B.

Friendship is not inherited. This means, for example:

class D : public C
{
private:
   void foo() {
      // A and B cannot call this function
   }
}
查看更多
登录 后发表回答