Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why define a subclass as a friend of its own parent class?

Tags:

c++

I was looking through some C++ code written by a (now departed) coworker quite a long time ago, and found an odd class definition I'm trying to decipher.

class BaseClass
{
    friend SubClass1;
    friend SubClass2;
}

class SubClass1 : public BaseClass
{
    ...
}

class SubClass2 : public BaseClass
{
    ...
}

Is there a benefit to designing a class hierarchy this way? If you want access to private methods of BaseClass from the subclasses wouldn't you just move them to protected instead of private? I feel there is an idiom I'm missing here.

like image 820
whazzmaster Avatar asked Nov 17 '25 20:11

whazzmaster


2 Answers

It is hard to say without looking at the real design of the library, but the two approaches are not equivalent. Using friend in this way provides greater access to lesser types than you can get by declaring all members protected.

Greater access

The meaning of protected is not exactly grant access to all base members everywhere to the derived type, but rather grant access to the protected members of the base subobject inside the derived type. The difference is that a derived type cannot access protected members or a type that is not of its own type or derived types.

Consider two versions of a class one of which has all members protected and no friend declaration, another that has all members private and declares a subclass as a friend. Now consider that the derived type had a function:

struct derived : base {
   void f( base& b ) {
       //std::cout << b.protected_method() << std::endl; // Error
       std::cout << protected_method() << std::endl;     // Ok, accessing your own base
   }
};

In the case of using protected, the issue there is that protected does not let you tweak the contents of any object other than derived or types derived from derived, but the argument could be a base or any other type that extends base and it not otherwise related to derived.

This restriction is a bit less clear in some other use cases, and you might be able to obtain access to those protected members outside of your own hierarchy, just not in a direct simple way (I consider that a bug in the access specifier specification of the language).

On the other hand, if derived is a friend of the base the above code will compile, as derived is granted access to every base instance anywhere, be it a subobject of derived or not.

To lesser types

The protected access specifier is transtive, once you grant access through protected to a derived type, you are granting it to all types that derive from it, and also to any other type that might inherit directly from you. It is impossible to control what types are granted access and which are not. On the other hand friendship is precise, only the members of the types declared as friend will have access. Friendship is not transitive, so type other than your declared friends will have access.

like image 157
David Rodríguez - dribeas Avatar answered Nov 19 '25 09:11

David Rodríguez - dribeas


I don't know of any particular idiom that involves that, but a simple answer might be that they wished to expose private members only to a few subclasses out of many. Alternatively, they may simple not have understood the concept of protected members.

like image 33
Datalore Avatar answered Nov 19 '25 09:11

Datalore