468,771 Members | 1,892 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,771 developers. It's quick & easy.

Friends and Visual C++ Express 2005

t
Lippman's C++ Primer, 4th ed., p575 says:

Friendship is not inherited. Friends of the base class have no
special access to members of its derived class. If a base class is
granted friendship, only the base has special access. Classes derived
from that base have no access to the class granting friendship.

I tried this in Visual C++ 2005 Express, and it seems to only
implement half of the friendship rules above.

Example code:

=================================================

class A2;

class A
{
friend class B;
friend void g(A, A2);
private:
int x;
};

class A2 : public A
{
private:
int x2;
};

class B
{
public:
void f(A a) { a.x; }

void f2(A2 a2) { a2.x; a2.x2;}
// a2.x compiles, but a2.x2 gives compile error
// both statements in f2 should be compile errors ???
};

class B2 : public B
{
public:
// void f(A a) { a.x; } // gives compile error, as it should
};

void g(A a, A2 a2)
{
a.x; // compiles
a2.x; // compiles, but shouldn't ?
a2.x2; // doesn't compile
}

int main()
{
}

=================================================

Is Visual C++ 2005 Express not implementing friendship rules correctly?

Sep 22 '07 #1
11 1384
t wrote:
Lippman's C++ Primer, 4th ed., p575 says:

Friendship is not inherited. Friends of the base class have no
special access to members of its derived class. If a base class is
granted friendship, only the base has special access. Classes derived
from that base have no access to the class granting friendship.

I tried this in Visual C++ 2005 Express, and it seems to only
implement half of the friendship rules above.

Example code:

=================================================

class A2;

class A
{
friend class B;
friend void g(A, A2);
private:
int x;
};

class A2 : public A
{
private:
int x2;
};

class B
{
public:
void f(A a) { a.x; }

void f2(A2 a2) { a2.x; a2.x2;}
// a2.x compiles, but a2.x2 gives compile error
// both statements in f2 should be compile errors ???
};

class B2 : public B
{
public:
// void f(A a) { a.x; } // gives compile error, as it should
};

void g(A a, A2 a2)
{
a.x; // compiles
a2.x; // compiles, but shouldn't ?
a2.x2; // doesn't compile
}

int main()
{
}

=================================================

Is Visual C++ 2005 Express not implementing friendship rules correctly?
the compiler is correct.
>
"friend of farther(A)" (B, g) is not necessarily friend of son(A2).

--
Thanks
Barry
Sep 22 '07 #2
t
I'm not sure. There are lines in the code I gave involving "a2.x"
that are compiling that I don't think should be compiling. It seems
like the Visual C++ compiler is using more lenient friendship rules.

The example in Lippman is different. I'll just type it out.
See "// my comment:" for my comments below. All other comments
are Lippman's.

==================================================

class Base {
friend class Frnd;
protected:
int i;
};

// Frnd has no access to members in D1
class D1 : public Base {
protected:
int j;
};

class Frnd {
public:
int mem(Base b) { return b.i; } // ok: Frnd is friend to Base
int mem(D1 d) { return d.i; } // error: friendship doesn't inherit
// my comment: VC++ compiles this!
};

// D2 has no access to members in Base
class D2 : public Frnd {
public:
int mem(Base b) { return b.i; } // error: friendship doesn't
inherit
// my comment: VC++ flags this as error!
};

================================================== =======

Sep 22 '07 #3
"t" <tm****@Yahoo.comwrote in message
news:11**********************@r29g2000hsg.googlegr oups.com...
: Lippman's C++ Primer, 4th ed., p575 says:
:
: Friendship is not inherited. Friends of the base class have no
: special access to members of its derived class. If a base class is
: granted friendship, only the base has special access. Classes derived
: from that base have no access to the class granting friendship.
:
: I tried this in Visual C++ 2005 Express, and it seems to only
: implement half of the friendship rules above.
:
: Example code:
:
: =================================================
:
:
:
: class A2;
:
: class A
: {
: friend class B;
: friend void g(A, A2);
: private:
: int x;
: };
:
: class A2 : public A
: {
: private:
: int x2;
: };
:
: class B
: {
: public:
: void f(A a) { a.x; }
:
: void f2(A2 a2) { a2.x; a2.x2;}
: // a2.x compiles, but a2.x2 gives compile error
: // both statements in f2 should be compile errors ???
a2.x is ok, without "inheritance of friendship":
A is a *public* base class of A2, so a2 can be used
as an object of type A (without friendship). And
because B is a friend of A, B::f2 has access to A::x.

: };
:
: class B2 : public B
: {
: public:
: // void f(A a) { a.x; } // gives compile error, as it should
Right: this is what demonstrates the limitation
described in Lippman's paragraph quoted above.

: };
:
: void g(A a, A2 a2)
: {
: a.x; // compiles
: a2.x; // compiles, but shouldn't ?
Again: seeing that a2 is of type A does not require friendship,
because A is a public base class of A2.

: a2.x2; // doesn't compile
: }
:
: int main()
: {
: }
:
: =================================================
:
: Is Visual C++ 2005 Express not implementing friendship rules
correctly?

The above code at least seems to be handled correctly.
hth -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <http://www.brainbench.com

Sep 22 '07 #4

"t" <tm****@Yahoo.comwrote in message
news:11**********************@50g2000hsm.googlegro ups.com...
: I'm not sure. There are lines in the code I gave involving "a2.x"
: that are compiling that I don't think should be compiling. It seems
: like the Visual C++ compiler is using more lenient friendship rules.
:
: The example in Lippman is different. I'll just type it out.
: See "// my comment:" for my comments below. All other comments
: are Lippman's.
:
: ==================================================
:
: class Base {
: friend class Frnd;
: protected:
: int i;
: };
:
: // Frnd has no access to members in D1
: class D1 : public Base {
: protected:
: int j;
: };
:
: class Frnd {
: public:
: int mem(Base b) { return b.i; } // ok: Frnd is friend to Base
: int mem(D1 d) { return d.i; } // error: friendship doesn't inherit
Well, my understanding would be that this is a typo in the book,
or in your transcription of it.
The code was probably meant to be:
int mem(D1 d) { return d.j; } // error: friendship doesn't inherit

: // my comment: VC++ compiles this!
: };
:
: // D2 has no access to members in Base
: class D2 : public Frnd {
: public:
: int mem(Base b) { return b.i; } // error: friendship doesn't
: inherit
: // my comment: VC++ flags this as error!
: };

hth --Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <http://www.brainbench.com

Sep 22 '07 #5
t wrote:
I'm not sure. There are lines in the code I gave involving "a2.x"
that are compiling that I don't think should be compiling. It seems
like the Visual C++ compiler is using more lenient friendship rules.

The example in Lippman is different. I'll just type it out.
See "// my comment:" for my comments below. All other comments
are Lippman's.
Well, use the former example rather than this one
void g(A a, A2 a2)
{
a2.x; // compiles, but shouldn't ?
}

here a2.x is can be interpreted this way:

int A::*pm = &A::x; // (1)
a2.*x; // (2)

then the access control actually takes place on (1),
since g is a friend of A, then taking a private pointer to member of A
is legal.

So, to conclude, when we do inheritance, the members of the base class
are not members of the derived class. The derived class only *inherits*
them.
--
Thanks
Barry
Sep 22 '07 #6
t
:
: class Frnd {
: public:
: int mem(Base b) { return b.i; } // ok: Frnd is friend to Base
: int mem(D1 d) { return d.i; } // error: friendship doesn't inherit
Well, my understanding would be that this is a typo in the book,
or in your transcription of it.
The code was probably meant to be:
int mem(D1 d) { return d.j; } // error: friendship doesn't inherit
It must be a typo in the book then.

Sep 22 '07 #7
t
On Sep 22, 1:30 am, Barry <dhb2...@gmail.comwrote:
Well, use the former example rather than this one
void g(A a, A2 a2)
{
a2.x; // compiles, but shouldn't ?

}

here a2.x is can be interpreted this way:

int A::*pm = &A::x; // (1)
a2.*x; // (2)

then the access control actually takes place on (1),
since g is a friend of A, then taking a private pointer to member of A
is legal.

So, to conclude, when we do inheritance, the members of the base class
are not members of the derived class. The derived class only *inherits*
them.

--
Thanks
Barry
Is there a good reason for friendship to be like this? That friends
of A have access to the A parts of subclasses of A. This doesn't seem
"natural" or "right" to me w/ the way my mental model of C++ has been
building up. Maybe it's because I don't understand the underlying
mechanics of C++. It seems like there are some linguistic rules in
play that don't fit well w/ my mental model (I tend to think
geometrically rather than algebraically).

Or is this one of those rules that have no good basis but I simply
have to remember?

Sep 22 '07 #8
t
Let me quote the rest of Lippman's section on "Friendship and
Inheritance" p575-6, excluding the code. It seems to contradict what
Barry and Ivan are telling me.

"Friendship is not inherited. Friends of the base class have no
special access to members of its derived class. If a base class is
granted friendship, only the base has special access. Classes derived
from that base have no access to the class granting friendship.

....

If a derived class wants to grant access to its members to the friends
of its base class, the derived class must do so explicitly. Friends
of the base have no special access to types derived from that base
class. Similarly, if a base and its derived types all need access to
another class, that class must specifically grant access to the base
and each derived class."

Sep 22 '07 #9
On Sep 22, 1:30 am, Barry <dhb2...@gmail.comwrote:
t wrote:
I'm not sure. There are lines in the code I gave involving "a2.x"
that are compiling that I don't think should be compiling. It seems
like the Visual C++ compiler is using more lenient friendship rules.
The example in Lippman is different. I'll just type it out.
See "// my comment:" for my comments below. All other comments
are Lippman's.

Well, use the former example rather than this one
void g(A a, A2 a2)
{
a2.x; // compiles, but shouldn't ?

}

here a2.x is can be interpreted this way:

int A::*pm = &A::x; // (1)
a2.*x; // (2)

then the access control actually takes place on (1),
since g is a friend of A, then taking a private pointer to member of A
is legal.

So, to conclude, when we do inheritance, the members of the base class
are not members of the derived class. The derived class only *inherits*
them.
Actually, the members of a base class inherited by a derived class,
are in fact members of the derived class as well:

"Unless redefined in the derived class, members of a base class
are also considered to be members of the derived class."[10/1]

So, in this example, B has two potential routes to get to A2::x -
either through A2::A2::x or via A2::A::x. Since B is a friend of A's,
it can reach A2::x through A::x (since the "x" in either A or A2 is
the same member). And whenever there is more than one ways to access a
member of a class, a C++ compiler must choose the one that grants the
most access - which in this case is through B's friend, A.

Greg

Sep 22 '07 #10
Greg Herlihy wrote:
On Sep 22, 1:30 am, Barry <dhb2...@gmail.comwrote:
>t wrote:
>>I'm not sure. There are lines in the code I gave involving "a2.x"
that are compiling that I don't think should be compiling. It seems
like the Visual C++ compiler is using more lenient friendship rules.
The example in Lippman is different. I'll just type it out.
See "// my comment:" for my comments below. All other comments
are Lippman's.
Well, use the former example rather than this one
void g(A a, A2 a2)
{
a2.x; // compiles, but shouldn't ?

}

here a2.x is can be interpreted this way:

int A::*pm = &A::x; // (1)
a2.*x; // (2)

then the access control actually takes place on (1),
since g is a friend of A, then taking a private pointer to member of A
is legal.

So, to conclude, when we do inheritance, the members of the base class
are not members of the derived class. The derived class only *inherits*
them.

Actually, the members of a base class inherited by a derived class,
are in fact members of the derived class as well:

"Unless redefined in the derived class, members of a base class
are also considered to be members of the derived class."[10/1]

So, in this example, B has two potential routes to get to A2::x -
either through A2::A2::x or via A2::A::x. Since B is a friend of A's,
it can reach A2::x through A::x (since the "x" in either A or A2 is
the same member). And whenever there is more than one ways to access a
member of a class, a C++ compiler must choose the one that grants the
most access - which in this case is through B's friend, A.
You're right, I should've checked out the standard first.

#include <iostream>

struct A
{
void f() {

}
};

struct B : A
{
void g() {
std::cout << typeid(&B::f).name() << std::endl;
std::cout << typeid(&A::f).name() << std::endl;
}
};

int main()
{
B b;
b.g();
}

produced output by MSVC8:
void (__thiscall A::*)(void)
void (__thiscall A::*)(void)

I judged membership by this way. So I guess I was wrong.

--
Thanks
Barry
Sep 22 '07 #11
"t" <tm****@Yahoo.comwrote in message
news:11**********************@r29g2000hsg.googlegr oups.com...
: On Sep 22, 1:30 am, Barry <dhb2...@gmail.comwrote:
:
: Well, use the former example rather than this one
: void g(A a, A2 a2)
: {
: a2.x; // compiles, but shouldn't ?
: >
: }
: >
: here a2.x is can be interpreted this way:
: >
: int A::*pm = &A::x; // (1)
: a2.*x; // (2)
: >
: then the access control actually takes place on (1),
: since g is a friend of A, then taking a private pointer to member of
A
: is legal.
: >
: So, to conclude, when we do inheritance, the members of the base
class
: are not members of the derived class. The derived class only
*inherits*
: them.
: >
: --
: Thanks
: Barry
:
: Is there a good reason for friendship to be like this? That friends
: of A have access to the A parts of subclasses of A. This doesn't seem
: "natural" or "right" to me w/ the way my mental model of C++ has been
: building up. Maybe it's because I don't understand the underlying
: mechanics of C++. It seems like there are some linguistic rules in
: play that don't fit well w/ my mental model (I tend to think
: geometrically rather than algebraically).
:
: Or is this one of those rules that have no good basis but I simply
: have to remember?

Well, if a class D publicly derives from A, instances of D *want* to
behave as if they were of type A. Otherwise, the subclass can
use private inheritance, or containement. If an instance of D
*is* an instance of A, friends as well may treat it as an A.
This seems fully logical and intuitive to me.

However, we do not want friendship to be "viral", which is what
the restrictions are about: a subclass shall not benefit from
or suffer from the consequences of the friedships of its parents.

--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <http://www.brainbench.com

Sep 22 '07 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Bootstrap Bill | last post: by
3 posts views Thread by clintonG | last post: by
5 posts views Thread by Patrick Olurotimi Ige | last post: by
2 posts views Thread by Progman | last post: by
45 posts views Thread by mistral | last post: by
1 post views Thread by Dr T | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.