need for friend function

  • Thread starter subramanian100in
  • Start date
S

subramanian100in

Stroustrup, in his book TC++PL 3rd Edition, in page 16, under the
section '1.8 Advice' has mentioned the following:
[2] [a] Don't use global data(use members)
Don't use global functions
[c] Don't use public data members.
[d] Don't use friends, except to avoid [a] or [c].

Consider the following scenarios:

Scenario 1:
----------------
class Test
{
friend ostream & operator<<(ostream &os, const Test &ref);
}

Here the friend ostream &operator<<() can be avoided by providing a
Test::print_output() function and expect the user to explicitly call
Test_obj.print_output(os) for an object Test_obj of type Test.

Scenario 2:
----------------
class Test
{
friend Test operator+(const Test &arg1, const Test &arg2);
}

This friend function can be avoided as follows:

class Test
{
Test &operator+=(const Test &ref);
}

Test operator+(const Test &arg1, const &arg2)
{
Test temp(arg1);
return temp += arg2;
}

Scenario 3:
----------------
Consider invert(m) for inverting a 'Matrix m' to the alternative
m.invert()
By providing Matrix::invert(), here also the friend function can be
avoided.

I want to know if there are some guidelines and examples where the
need for using a friend function is unavoidable.

Kindly explain.

Thanks
V.Subramanian
 
V

Victor Bazarov

[..]
I want to know if there are some guidelines and examples where the
need for using a friend function is unavoidable.

Here is the thing: absence of evidence is not evidence of absence.
If I've never encountered in my whole life any guidelines and/or
examples where using a friend function is unavoidable, it does not
mean there isn't any. However, consider this: if there are better
ways of doing something, and you have no reason for *not* using one
of the better ways, then the "not so good" mechanism is avoidable.
Invert that, and you get this: if there are compelling reasons not
to use any of the ways to avoid something, then this something
becomes unavoidable. If for some reason you cannot grant access
to some private data to everybody (declare the data public or
protected), *and* you cannot make certain function a member of the
class containing the private data, then you are stuck with making
the function a friend. I know, it's not concrete, but that's the
essence, AFA I'm concerned.

V
 
T

terminator

Stroustrup, in his book TC++PL 3rd Edition, in page 16, under the
section '1.8 Advice' has mentioned the following:
[2] [a] Don't use global data(use members)
Don't use global functions
[c] Don't use public data members.
[d] Don't use friends, except to avoid [a] or [c].

Consider the following scenarios:

Scenario 1:
----------------
class Test
{
friend ostream & operator<<(ostream &os, const Test &ref);

}

Here the friend ostream &operator<<() can be avoided by providing a
Test::print_output() function and expect the user to explicitly call
Test_obj.print_output(os) for an object Test_obj of type Test.

Scenario 2:
----------------
class Test
{
friend Test operator+(const Test &arg1, const Test &arg2);

}

This friend function can be avoided as follows:

class Test
{
Test &operator+=(const Test &ref);

}

Test operator+(const Test &arg1, const &arg2)
{
Test temp(arg1);
return temp += arg2;

}

Scenario 3:
----------------
Consider invert(m) for inverting a 'Matrix m' to the alternative
m.invert()
By providing Matrix::invert(), here also the friend function can be
avoided.

I want to know if there are some guidelines and examples where the
need for using a friend function is unavoidable.

Kindly explain.



class A;
class B;
class C

C foo(A a,B b){
//I need to access private members of A,B and C.
//I must be a friend of at least two of them.
};

regards,
FM.
 
G

GArlington

Stroustrup, in his book TC++PL 3rd Edition, in page 16, under the
section '1.8 Advice' has mentioned the following:
[2] [a] Don't use global data(use members)
Don't use global functions
[c] Don't use public data members.
[d] Don't use friends, except to avoid [a] or [c].

Consider the following scenarios:
Scenario 1:
----------------
class Test
{
friend ostream & operator<<(ostream &os, const Test &ref);

Here the friend ostream &operator<<() can be avoided by providing a
Test::print_output() function and expect the user to explicitly call
Test_obj.print_output(os) for an object Test_obj of type Test.
Scenario 2:
----------------
class Test
{
friend Test operator+(const Test &arg1, const Test &arg2);

This friend function can be avoided as follows:
class Test
{
Test &operator+=(const Test &ref);

Test operator+(const Test &arg1, const &arg2)
{
Test temp(arg1);
return temp += arg2;

Scenario 3:
----------------
Consider invert(m) for inverting a 'Matrix m' to the alternative
m.invert()
By providing Matrix::invert(), here also the friend function can be
avoided.
I want to know if there are some guidelines and examples where the
need for using a friend function is unavoidable.
Kindly explain.

class A;
class B;
class C

C foo(A a,B b){
//I need to access private members of A,B and C.
//I must be a friend of at least two of them.

};

regards,
FM.


Most of the time you can use public methods instead...
 
C

Christopher

Stroustrup, in his book TC++PL 3rd Edition, in page 16, under the
section '1.8 Advice' has mentioned the following:
[2] [a] Don't use global data(use members)
Don't use global functions
[c] Don't use public data members.
[d] Don't use friends, except to avoid [a] or [c].

Consider the following scenarios:
Scenario 1:
----------------
class Test
{
friend ostream & operator<<(ostream &os, const Test &ref);

Here the friend ostream &operator<<() can be avoided by providing a
Test::print_output() function and expect the user to explicitly call
Test_obj.print_output(os) for an object Test_obj of type Test.
Scenario 2:
----------------
class Test
{
friend Test operator+(const Test &arg1, const Test &arg2);

This friend function can be avoided as follows:
class Test
{
Test &operator+=(const Test &ref);

Test operator+(const Test &arg1, const &arg2)
{
Test temp(arg1);
return temp += arg2;

Scenario 3:
----------------
Consider invert(m) for inverting a 'Matrix m' to the alternative
m.invert()
By providing Matrix::invert(), here also the friend function can be
avoided.
I want to know if there are some guidelines and examples where the
need for using a friend function is unavoidable.
Kindly explain.

class A;
class B;
class C

C foo(A a,B b){
//I need to access private members of A,B and C.
//I must be a friend of at least two of them.

};

regards,
FM.


Sorry term, I think that is a very bad example. you may give the OP
the idea that any constructor with an argument will have to be a
friend of the argument type, which is quite false.

A and B should have public accessors, which the constructor of C can
use. If for some reason A and B cannot provide accessors, than that is
the reason for making them friends to C. However, the example does not
illustrate that unknown reason for A and B not having accessors.
 
R

robertwessel2

[..]
I want to know if there are some guidelines and examples where the
need for using a friend function is unavoidable.

Here is the thing: absence of evidence is not evidence of absence.
If I've never encountered in my whole life any guidelines and/or
examples where using a friend function is unavoidable, it does not
mean there isn't any. However, consider this: if there are better
ways of doing something, and you have no reason for *not* using one
of the better ways, then the "not so good" mechanism is avoidable.
Invert that, and you get this: if there are compelling reasons not
to use any of the ways to avoid something, then this something
becomes unavoidable. If for some reason you cannot grant access
to some private data to everybody (declare the data public or
protected), *and* you cannot make certain function a member of the
class containing the private data, then you are stuck with making
the function a friend. I know, it's not concrete, but that's the
essence, AFA I'm concerned.


My complaint about friendship is that its too coarse grained. I
almost never see the situation where one class actually needs to
access the private data members of another (and that's usually pretty
easy to design around, even if you just add some getters and
setters). What I have run into is the situation where two or more
classes need to share some interfaces within the group, but not with
classes outside that group.

While there are ways around that (notably making the semi-public
interfaces part of derived classes, although that brings other
problems, particularly the need to use a factory method), none of the
workarounds are all that clean (of course, neither is excessively
permissive friendship).
 
V

Victor Bazarov

[..]
My complaint about friendship is that its too coarse grained. I
almost never see the situation where one class actually needs to
access the private data members of another (and that's usually pretty
easy to design around, even if you just add some getters and
setters). What I have run into is the situation where two or more
classes need to share some interfaces within the group, but not with
classes outside that group.

While there are ways around that (notably making the semi-public
interfaces part of derived classes, although that brings other
problems, particularly the need to use a factory method), none of the
workarounds are all that clean (of course, neither is excessively
permissive friendship).

To provide the functionality where only members of the group have
access to each other's privates ("family"? :)) you can define
a "shared" class which will be the friend of them all and though
which they will request the access. Kind of like this:

class A {
int a;
friend class P;
public:
void foo();
};

class B {
int b;
friend class P;
public:
void foo();
};

class P { // everything is private
friend class A;
friend class B;
static int &a(A& ai) { return ai.a; }
static int &b(B& bi) { return bi.b; }
};

void A::foo() {
B myb;
a = P::b(myb);
}

void B::foo() {
A mya;
b = P::a(mya);
}

int main() {
A a;
B b;
a.foo();
b.foo();
}

Note that 'A' is not a friend of 'B', nor 'B' is a friend of 'A'.

V
 
R

robertwessel2

[..]
My complaint about friendship is that its too coarse grained. I
almost never see the situation where one class actually needs to
access the private data members of another (and that's usually pretty
easy to design around, even if you just add some getters and
setters). What I have run into is the situation where two or more
classes need to share some interfaces within the group, but not with
classes outside that group.
While there are ways around that (notably making the semi-public
interfaces part of derived classes, although that brings other
problems, particularly the need to use a factory method), none of the
workarounds are all that clean (of course, neither is excessively
permissive friendship).

To provide the functionality where only members of the group have
access to each other's privates ("family"? :)) you can define
a "shared" class which will be the friend of them all and though
which they will request the access. Kind of like this:

class A {
int a;
friend class P;
public:
void foo();
};

class B {
int b;
friend class P;
public:
void foo();
};

class P { // everything is private
friend class A;
friend class B;
static int &a(A& ai) { return ai.a; }
static int &b(B& bi) { return bi.b; }
};

void A::foo() {
B myb;
a = P::b(myb);
}

void B::foo() {
A mya;
b = P::a(mya);
}

int main() {
A a;
B b;
a.foo();
b.foo();
}

Note that 'A' is not a friend of 'B', nor 'B' is a friend of 'A'.


Yes, I've seen that pattern (more precisely with accessor classes for
each class in the family, rather than one big one for the whole
family), but it's far from pretty. At least with the derived class
approach you can call the functions with the normal type resolution
and syntax, although it's difficult to extend that to multiple
families (although that's only been an issue on a couple of occasions).
 
R

Rahul

[..]
My complaint about friendship is that its too coarse grained. I
almost never see the situation where one class actually needs to
access the private data members of another (and that's usually pretty
easy to design around, even if you just add some getters and
setters). What I have run into is the situation where two or more
classes need to share some interfaces within the group, but not with
classes outside that group.
While there are ways around that (notably making the semi-public
interfaces part of derived classes, although that brings other
problems, particularly the need to use a factory method), none of the
workarounds are all that clean (of course, neither is excessively
permissive friendship).

To provide the functionality where only members of the group have
access to each other's privates ("family"? :)) you can define
a "shared" class which will be the friend of them all and though
which they will request the access. Kind of like this:

class A {
int a;
friend class P;
public:
void foo();
};

class B {
int b;
friend class P;
public:
void foo();
};

class P { // everything is private
friend class A;
friend class B;
static int &a(A& ai) { return ai.a; }
static int &b(B& bi) { return bi.b; }
};

static functions accessing non-static member variables?
 
A

Abhishek Padmanabh

static functions accessing non-static member variables?

Would that be a problem? Note that the static functions belong to
class P and the non-static members are of classes A and B.
 
M

ManicQin

class A {
int a;
friend class P;
public:
void foo();
};

class B {
int b;
friend class P;
public:
void foo();
};

class P { // everything is private
friend class A;
friend class B;
static int &a(A& ai) { return ai.a; }
static int &b(B& bi) { return bi.b; }
};

void A::foo() {
B myb;
a = P::b(myb);
}

void B::foo() {
A mya;
b = P::a(mya);
}

int main() {
A a;
B b;
a.foo();
b.foo();
}

Note that 'A' is not a friend of 'B', nor 'B' is a friend of 'A'.

that is a one ugly pattern...
I'm not sure you should use this one...

Why strousrup is advising not to use friends?
 
V

Victor Bazarov

ManicQin said:
[..]
Why strousrup is advising not to use friends?
^^^^^^^^^
I am not sure who (or what) that is.

Friendship goes against the data/implementation hiding principle.
If you make something private, that's really only for you to see.

V
 
T

terminator

Stroustrup, in his book TC++PL 3rd Edition, in page 16, under the
section '1.8 Advice' has mentioned the following:
[2] [a] Don't use global data(use members)
Don't use global functions
[c] Don't use public data members.
[d] Don't use friends, except to avoid [a] or [c].
Consider the following scenarios:
Scenario 1:
----------------
class Test
{
friend ostream & operator<<(ostream &os, const Test &ref);
}
Here the friend ostream &operator<<() can be avoided by providing a
Test::print_output() function and expect the user to explicitly call
Test_obj.print_output(os) for an object Test_obj of type Test.
Scenario 2:
----------------
class Test
{
friend Test operator+(const Test &arg1, const Test &arg2);
}
This friend function can be avoided as follows:
class Test
{
Test &operator+=(const Test &ref);
}
Test operator+(const Test &arg1, const &arg2)
{
Test temp(arg1);
return temp += arg2;
}
Scenario 3:
----------------
Consider invert(m) for inverting a 'Matrix m' to the alternative
m.invert()
By providing Matrix::invert(), here also the friend function can be
avoided.
I want to know if there are some guidelines and examples where the
need for using a friend function is unavoidable.
Kindly explain.

class A;
class B;
class C
C foo(A a,B b){
//I need to access private members of A,B and C.
//I must be a friend of at least two of them.

regards,
FM.

Sorry term, I think that is a very bad example. you may give the OP
the idea that any constructor with an argument will have to be a
friend of the argument type, which is quite false.


I did not mean that every function needs public access to its
operands/return.
A and B should have public accessors, which the constructor of C can
use. If for some reason A and B cannot provide accessors, than that is
the reason for making them friends to C. However, the example does not
illustrate that unknown reason for A and B not having accessors.

not always possible if public interface A,B and C is interelated , you
can not avoid friend declarations.

regards,
FM.
 
T

terminator

Would that be a problem? Note that the static functions belong to
class P and the non-static members are of classes A and B.

that does not change any thing;but you are right in that the only
difference between none static and static members is that the former
do not get a hidden 'this' parameter.

regards,
FM.
 
T

terminator

ManicQin said:
[..]
Why strousrup is advising not to use friends?

^^^^^^^^^
I am not sure who (or what) that is.

Friendship goes against the data/implementation hiding principle.
If you make something private, that's really only for you to see.

V

some languages(certainly not C++) indroduce some 'internal' access
specifier that bounds access to the same module;something like what
'static' declaration of functions does in C.

regards,
FM.
 
A

Abhishek Padmanabh

that does not change any thing;but you are right in that the only
difference between none static and static members is that the former
do not get a hidden 'this' parameter.

I don't know what you tried to mean here but there is no relation to
the 'this' pointer in the above example's case. I did not say anything
related to static and non-static members and the this pointer
associated with the non-static member functions. That fact does not
form the basis of why the code above works. The static functions in P
just need an object of type A and B to access their private members.
 
J

James Kanze

ManicQin said:
[..]
Why strousrup is advising not to use friends?
^^^^^^^^^
I am not sure who (or what) that is.

A misspelling of Stroustrup?
Friendship goes against the data/implementation hiding
principle. If you make something private, that's really only
for you to see.

I don't think that Stroustrup advises unconditionally against
friends. If he had felt that there was never a reason to use a
friend, he wouldn't have added the concept to the language.

The important thing, I think, is to consider friends as part of
the interface of your class. Don't (normally) make anything a
friend that isn't implemented as part of your class
implementation. Used correctly, friends increase encapsulation
and hiding.
 
M

ManicQin

ManicQin said:
[..]
Why strousrup is advising not to use friends?
^^^^^^^^^
I am not sure who (or what) that is.

A misspelling of Stroustrup?
Friendship goes against the data/implementation hiding
principle. If you make something private, that's really only
for you to see.

I don't think that Stroustrup advises unconditionally against
friends. If he had felt that there was never a reason to use a
friend, he wouldn't have added the concept to the language.

The important thing, I think, is to consider friends as part of
the interface of your class. Don't (normally) make anything a
friend that isn't implemented as part of your class
implementation. Used correctly, friends increase encapsulation
and hiding.


first thing, victor! a strousrup is another name for Cthulhu.;)
second, It's true that "Friendship goes against the data/
implementation hiding" but I think that two classes which are bound
with a friend relationship could be looked as an inclosed interface.
 
V

Victor Bazarov

ManicQin said:
ManicQin wrote:
[..]
Why strousrup is advising not to use friends?
^^^^^^^^^
I am not sure who (or what) that is.

A misspelling of Stroustrup?
Friendship goes against the data/implementation hiding
principle. If you make something private, that's really only
for you to see.

I don't think that Stroustrup advises unconditionally against
friends. If he had felt that there was never a reason to use a
friend, he wouldn't have added the concept to the language.

The important thing, I think, is to consider friends as part of
the interface of your class. Don't (normally) make anything a
friend that isn't implemented as part of your class
implementation. Used correctly, friends increase encapsulation
and hiding.


first thing, victor! a strousrup is another name for Cthulhu.;)
second, It's true that "Friendship goes against the data/
implementation hiding" but I think that two classes which are bound
with a friend relationship could be looked as an inclosed interface.

Well, manicqin, you need to elaborate. An "enclosed" (did you mean
'enclosed'? I am hoping you did) interface: enclosed by what, or
enclosed where, or enclosed with what? Also, remember that frienship
is non-symmetrical (while parts of interfaces are, usually).

V
 
M

ManicQin

ManicQin said:
ManicQin wrote:
[..]
Why strousrup is advising not to use friends?
^^^^^^^^^
I am not sure who (or what) that is.
A misspelling of Stroustrup?
Friendship goes against the data/implementation hiding
principle. If you make something private, that's really only
for you to see.
I don't think that Stroustrup advises unconditionally against
friends. If he had felt that there was never a reason to use a
friend, he wouldn't have added the concept to the language.
The important thing, I think, is to consider friends as part of
the interface of your class. Don't (normally) make anything a
friend that isn't implemented as part of your class
implementation. Used correctly, friends increase encapsulation
and hiding.
first thing, victor! a strousrup is another name for Cthulhu.;)
second, It's true that "Friendship goes against the data/
implementation hiding" but I think that two classes which are bound
with a friend relationship could be looked as an inclosed interface.

Well, manicqin, you need to elaborate. An "enclosed" (did you mean
'enclosed'? I am hoping you did) interface: enclosed by what, or
enclosed where, or enclosed with what? Also, remember that frienship
is non-symmetrical (while parts of interfaces are, usually).

V

I meant inclosed... my dictionary (babylon) says the "enclosed" and
"inclosed" are the same
(maybe its like color and colour...) but maybe, just maybe it was'nt
the right word to use.

ok what I meant is (IMHO) that the concept of interface is not applied
only to the in/out operations of a single class, a set of classes
could form an interface too.
(ctrl+c ctrl+v) Friendship goes against the data/implementation hiding
of a class but not of a complete interface.
of course you could misuse the interface and "hack" your way in to a
class threw the friendship but the same could be told about
protected...

p.s. please forgive me for my summarized definition of an interface.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top