Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

New feature in C++ wanted: friend limited to one function only in a class

27 views
Skip to first unread message

JiiPee

unread,
Aug 25, 2022, 1:11:37 PM8/25/22
to
I had this situation many times, that I wanted to use friend in class
but I dont want friend be able to get
access to ALL members, only maybe one function. I wish there was a
feature in C++ like this:

class Parent
{
private:
void foo() { : friend Child // new feature
}

void foo2() {
}
};

and now Child can get access to foo() and ONLY it:

class Child
{
public:
Parent* m_parent{nullptr}; // later initialized ...
void foo3() {
// Can access only foo()
m_parent->foo(); // this is OK
// cannot access any other privates
m_parent->foo2(); // this is NOT OK
}
};

Can anybody suggest this to Bjarne? hehe

Alf P. Steinbach

unread,
Aug 25, 2022, 2:13:36 PM8/25/22
to
On 25 Aug 2022 19:11, JiiPee wrote:
>
> class Parent
> {
> private:
>     void foo() { : friend Child // new feature
>     }
>
>     void foo2() {
>     }
> };
>
> and now Child can get access to foo() and ONLY it:
>
> class Child
> {
> public:
>     Parent* m_parent{nullptr}; // later initialized ...
>     void foo3() {
>         // Can access only foo()
>         m_parent->foo(); // this is OK
>         // cannot access any other privates
>         m_parent->foo2(); // this is NOT OK
>     }
> };

You can easily work around that limitation, like this:


class Child;

class Parent
{
public:
class Restricted
{
friend class Child;

static void foo( Parent& self ) //: friend Child
{
self.foo();
}
};

private:
void foo() {}
void foo2() {}
};

class Child
{
public:
Parent* m_parent{nullptr}; // later initialized ...

void foo3() {
// Can access only foo()
Parent::Restricted::foo( *m_parent ); // this is OK
// cannot access any other privates
#ifdef FAIL
m_parent->foo2(); // this is NOT OK
#endif
}
};


- Alf

JiiPee

unread,
Aug 25, 2022, 4:11:47 PM8/25/22
to
On 25/08/2022 21:00, Stefan Ram wrote:
> JiiPee <kerrttuPo...@gmail.com> writes:
>> Can anybody suggest this to Bjarne? hehe
>
> Until then you could use inheritance.

New idea for me. Also, can put another class inside the other one
preventing the friend to get acces to the inside class.


JiiPee

unread,
Aug 25, 2022, 4:13:59 PM8/25/22
to
yes thats a good one. I used similar before. although I still think the
new friend might be useful, if normal friend is also there.

Manfred

unread,
Aug 25, 2022, 7:59:55 PM8/25/22
to
I don't think this would be a good idea ("selective" friendship, not
contacting Bjarne..)
- friend by itself should be used parsimoniously: it goes against
encapsulation, so more often than not it is a symptom of poor design
(exceptions apply, but they are in fact exceptions)
- "selective" friendship, in the way you are suggesting, breaks
encapsulation even more, in that it introduces a new level of its
fragmentation.

Others have given solutions that do what you are trying to do.
If I had to address this issue, I'd look for a different and possibly
more consistent design, e.g. simply:

class Parent_public
{
public:
void foo();
};

class Parent : public Parent_public
{
private:
void foo2();
};

JiiPee

unread,
Aug 26, 2022, 12:19:31 AM8/26/22
to
On 26/08/2022 02:59, Manfred wrote:
> class Parent_public
> {
> public:
>   void foo();
> };
>
> class Parent : public Parent_public
> {
> private:
>   void foo2();
> };


A good idea, and I might use this also. Although a small "problem" I see
here is that it complicates the code a little more (more layers and more
typing ).
This would be much shorter, what I suggested:

void foo2() { : friend Child

Only two words .

For me, I like it a little more if its less typing and more simple.
But ok, maybe there is a logical reason not to support selective
friendship. But I have been looking that feature to be honest many
times. Because I rarely need one class have FULL friendship. Almost
always the friendship needs to be only partial.. normally 1-2 funktions.

JiiPee

unread,
Aug 26, 2022, 12:25:19 AM8/26/22
to
On 26/08/2022 02:59, Manfred wrote:
> - friend by itself should be used parsimoniously: it goes against
> encapsulation, so more often than not it is a symptom of poor design
> (exceptions apply, but they are in fact exceptions)

I also use rarely friends and its the last solution.
But... sometimes it is just easiest and most practical way, if the
classes are tightly linked with each others (like some kind of cache
class for another), and the classes go together "privately".

Also it keeps the code more simple. Instead of writing 20 new lines,
only 1-2 lines of code needed. So its kinda looking for a balance
between "best practices" and practicality/simple-short code.

But again, I only do it if no other easy solution and it has some logic
in it.

Paavo Helde

unread,
Aug 26, 2022, 5:14:00 AM8/26/22
to
You mean the C++ committee, not Bjarne. And I think everybody agrees C++
has already too many features, so it would be hard to propose a new one,
especially related to things like friends which are kind of frown upon
anyway.

Meanwhile, what about this? Instead of a private function accessible to
all friends define a public function accessible only to a "privileged
friend":

class Child1;
class Child2;

class Child1Key {
friend class Child1;
Child1Key() {}
};

class Child2Key {
friend class Child2;
Child2Key() {}
};

class Parent {
public:
void foo(Child1Key key) {}
void foo2(Child2Key key) {}
};

class Child1 {
public:
Parent* m_parent{ nullptr }; // later initialized ...
void foo3() {
// Can access only foo()
m_parent->foo(Child1Key{}); // this is OK
// cannot access any other privates
m_parent->foo2(Child2Key{}); // this is NOT OK
}
};





Michael S

unread,
Aug 26, 2022, 6:56:03 AM8/26/22
to
When somebody is obsessed with encapsulation enforcement
tools (private/protected/friend etc) it's a sure sign of him
having too much time and too little real work to do.
If I was your boss I'd knew how to handle that.

JiiPee

unread,
Aug 26, 2022, 12:29:58 PM8/26/22
to
On 26/08/2022 12:13, Paavo Helde wrote:
> class Child1 {
> public:
> Parent* m_parent{ nullptr }; // later initialized ...
> void foo3() {
> // Can access only foo()
> m_parent->foo(Child1Key{}); // this is OK
> // cannot access any other privates
> m_parent->foo2(Child2Key{}); // this is NOT OK
> }
> };

Thanks. a nice trick. Yes this is one of the best ways. I ll definitely
keep this in my mind. I think I have seen the "key" pattern before, this
seems similar.

Paavo Helde

unread,
Aug 26, 2022, 1:49:20 PM8/26/22
to
Yes, but also bear in mind that these kind of tricks are most often a
sign of serious over-engineering. If the intent is that foo() should be
called only by Child1 then just name if FooForChild1() and be done with it.


0 new messages