Is a class a friend of itself?

J

John

Hi,

In the code below, if I define member functions that take an A object,
then I am able to change protected data members of the passed in A
object. Does this mean that all members functions of a class or friend
functions of the same class? This surprised me. I can understand the
need for copy/assignment operators, but this seems to be true for all
member functions.

Thanks,
John

==================
#include <iostream>

class A
{
protected:
int y;
public:
virtual int abc() { return y+1; }

A() : y(1) {}
A(const A& a) { y = a.y; }

A& operator= ( A& a )
{
y = a.y;
return *this;
}

int xxx ( A& a ) { a.y =8; }

};


int main()
{

A a;
A b(a);
A c;

std::cout << a.abc() << "\n";
c = a;
std::cout << a.abc() << "\n";

std::cout << b.abc() << "\n";
std::cout << c.abc() << "\n";

c.xxx(a);
std::cout << a.abc() << "\n";

return 0;
}
=====
 
V

Victor Bazarov

John said:
[..] if I define member functions [of class A - vb] that take an A object,
then I am able to change protected data members of the passed in A
object. Does this mean that all members functions of a class or friend
functions of the same class?

"Friend"? No. Does the language allow access? Yes. The access to
private members is granted to members of the same class, and friends.
Explicitly. So, legally speaking, a class isn't a friend of itself.
> This surprised me. I can understand the
need for copy/assignment operators, but this seems to be true for all
member functions.

It is. I am not certain why you're surprised, though. Why not make it
consistent and allow *all* members access, not just copy-assignment.
What about copy-construction? Protected access is granted to all
members (considering that some functions need access to, say, protected
data) of derived classes. Why not grant access to private to all member
functions of self? Seems kinda logical to me.

V
 
J

Juha Nieminen

John said:
In the code below, if I define member functions that take an A object,
then I am able to change protected data members of the passed in A
object. Does this mean that all members functions of a class or friend
functions of the same class? This surprised me.

Why does it surprise you? Why shouldn't a class have access to its own
members?

If you wanted to restrict this, for whatever reason, exactly how would
you do that? You have no way of knowing whether a pointer is pointing to
the same object as 'this', other than actually making that check every
time a member is accessed, making every access slower. For what purpose?
 
J

John

It is. I am not certain why you're surprised, though. Why not make it
consistent and allow *all* members access, not just copy-assignment.
What about copy-construction? Protected access is granted to all
members (considering that some functions need access to, say, protected
data) of derived classes. Why not grant access to private to all member
functions of self? Seems kinda logical to me.

I see. Thanks.

John
 
A

Alan Woodland

Juha said:
Why does it surprise you? Why shouldn't a class have access to its own
members?

If you wanted to restrict this, for whatever reason, exactly how would
you do that? You have no way of knowing whether a pointer is pointing to
the same object as 'this', other than actually making that check every
time a member is accessed, making every access slower. For what purpose?

I think this assumption comes from the 'Java Bean' way of thinking about
interfaces, data and objects. I've definitely seen this question a lot
from Java programmers. Which is odd because Java allows the exact same
thing...

Alan
 
V

Victor Bazarov

Alan said:
I think this assumption comes from the 'Java Bean' way of thinking about
interfaces, data and objects. I've definitely seen this question a lot
from Java programmers. Which is odd because Java allows the exact same
thing...

I think some confuse access specifiers which are there to prevent errors
in programming, with "security attributes" which are usually aimed at
preventing malicious tempering, and sometimes (or often?) exist at the
object level instead of the class level.

V
 
S

Stefan Ram

Alan Woodland said:
I think this assumption comes from the 'Java Bean' way of thinking about
interfaces, data and objects. I've definitely seen this question a lot
from Java programmers. Which is odd because Java allows the exact same
thing...

One can also view it from the point of the decorator
pattern.

A decorator object wraps a core object. Now, think of the
decorator object as the »main« object: This main object
contains a core object, which in turn contains core
fields, but the main object can not access »its« core
fields directly, but only via the methods of the core
object.

This sometimes comes in handy so as to structure the
methods of an object into »core methods« and »hull
methods«. For example, when the object wraps an external
device and this devise changes, the source code of the
object needs to be modified to reflect the changes.
Sometimes, this can be done by only changing the core
methods. So, in this case, this separation helps to easily
find the part of the source code that needs to be
adjusted.
 
P

Pascal J. Bourguignon

Juha Nieminen said:
Why does it surprise you? Why shouldn't a class have access to its own
members?

That's the question.

If you have two objects of the same class, why should the first object
be allowed to fiddle with the fields of the other object:


void MyClass::myMethod(MyClass* other){
other->field=42; // !!!
}


Worse, other may actually be of a subclass of MyClass, in which the
implementation of the field is changed (eg.:
SubClass:setField(int aValue){ field=aValue*2; }
int SubClass:getField(int aValue){ return(field/2); }
) and then the fiddling will be wrong.

Unfortunately, C++ doesn't prevent it, and this is surprizing for a
language so up tight.

If you wanted to restrict this, for whatever reason, exactly how would
you do that?

We can only edict a style rule saying that fields should always be
accessed thru setters and getters.

You have no way of knowing whether a pointer is pointing to
the same object as 'this', other than actually making that check every
time a member is accessed, making every access slower. For what purpose?

Not really, with a declaration such as above, you know at least that
the other object has the wanted field. But of course, in presence of
subclasses, it's not enough.
 
A

Alan Woodland

Pascal said:
That's the question.

If you have two objects of the same class, why should the first object
be allowed to fiddle with the fields of the other object:


void MyClass::myMethod(MyClass* other){
other->field=42; // !!!
}


Worse, other may actually be of a subclass of MyClass, in which the
implementation of the field is changed (eg.:
SubClass:setField(int aValue){ field=aValue*2; }
int SubClass:getField(int aValue){ return(field/2); }
) and then the fiddling will be wrong.

Unfortunately, C++ doesn't prevent it, and this is surprizing for a
language so up tight.

Not really. (Part of) the point of encapsulation is the hiding of
internal data from code that doesn't/shouldn't know how the internals
work. I find it pretty hard to argue that a class doesn't know about
it's own internals!

There's a lot of cases when this behaviour is important - copy
constructors for one, but also with operator overloading (or doing the
equivalent thing without an operator for it).

For example consider an hypothetical BigNum class. To perform
multiplication between two of these requires detailed information about
the internals of both instances. Are you suggesting that being forced to
expose the guts of the internals via a public get in order to do this
would represent better design?
We can only edict a style rule saying that fields should always be
accessed thru setters and getters.



Not really, with a declaration such as above, you know at least that
the other object has the wanted field. But of course, in presence of
subclasses, it's not enough.

There's still an "IS A" relation there, so the previous comment applies
and it's not like you get access to the internals of the subclass. If
this scenario causes you problems then I'd argue that it's just the
manifestation of an larger problem within your design hierarchy.

Alan
 
J

Juha Nieminen

Pascal said:
That's the question.

If you have two objects of the same class, why should the first object
be allowed to fiddle with the fields of the other object:

I just can't see why it shouldn't. Somehow preventing it would make it
hard and awkward for one object to do something depending on the
internal state of another object of the same type. Copying/assigning an
object is just one example of where this is useful.

Think about static member functions: They don't have a 'this' pointer,
they can only be given objects as parameter. Should they be restricted
as well? Then exactly what would be the point in having static member
functions in the first place? They would be identical to regular
functions, and would require for the internals of the class to be exposed.
Worse, other may actually be of a subclass of MyClass, in which the
implementation of the field is changed

If 'field' is a private member of the base class (as it's what's being
discussed here), a subclass has no access to it, and thus cannot change
its implementation.
We can only edict a style rule saying that fields should always be
accessed thru setters and getters.

Private ones? Since the setters and getters are defined by the class
itself, exactly what would be the difference between using them and
accessing the variables directly? You would still be accessing the
private setters and getters of another object.

If you are talking about *public* setters and getters, then we are
going to a completely different realm of (dubious) object-oriented design.
Not really, with a declaration such as above, you know at least that
the other object has the wanted field. But of course, in presence of
subclasses, it's not enough.

I don't understand your argument about subclasses. A subclass cannot
change the implementation of a private member variable of a base class.
 
J

James Kanze

I just can't see why it shouldn't.

Practically, or theoretically:) ?

Theoretically (or logically, if you prefer), there are some very
good arguments in favor of using the object as the unity of
access control. Practically, it gets in the way in some
essential cases when value semantics are involved (copy
constructor, assignment), and since the goal is to provide a
fairly simple protection, and you control all of the member code
anyway, it makes more sense for access control to be at the
class level, and not the object level. And C++ has always
favored pragmatics over theory.
 

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,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top