Why friendship not applicable to function arguments

Discussion in 'C++' started by Ninan, Jun 29, 2006.

  1. Ninan

    Ninan Guest

    When compiling using gcc 2.95.3, I get the following error for the
    code snippet posted below.
    bash-2.03$ g++ membAccess.C
    membAccess.C: In function `int main()':
    membAccess.C:13: `struct A B::m_a' is private
    membAccess.C:38: within this context
    Is this how it is supposed to work or is this a compiler specific issue

    1 #include <iostream>
    2
    3
    4 struct A
    5 {
    6 int y;
    7 };
    8
    9 void useAalter (A* pA);
    10 class B
    11 {
    12
    13 A m_a;
    14 public:
    15 B (A& a)
    16 {
    17 m_a = a;
    18 }
    19 A* getA () { return &m_a;}
    20 friend void useAalter(A*pA);
    21 };
    22
    23 void useA (A* pA)
    24 {
    25 std::cout << pA->y << std::endl;
    26 }
    27
    28 void useAalter (A* pA)
    29 {
    30 std::cout << pA->y << std::endl;
    31 }
    32
    33 int main ()
    34 {
    35 A a = {45};
    36 B bInst (a);
    37 useA (bInst.getA());
    38 useAalter (&(bInst.m_a)) ;
    39 }
     
    Ninan, Jun 29, 2006
    #1
    1. Advertising

  2. Ninan

    Howard Guest

    "Ninan" <> wrote in message
    news:...
    > When compiling using gcc 2.95.3, I get the following error for the
    > code snippet posted below.
    > bash-2.03$ g++ membAccess.C
    > membAccess.C: In function `int main()':
    > membAccess.C:13: `struct A B::m_a' is private
    > membAccess.C:38: within this context
    > Is this how it is supposed to work or is this a compiler specific issue
    >
    > 1 #include <iostream>
    > 2
    > 3
    > 4 struct A
    > 5 {
    > 6 int y;
    > 7 };
    > 8
    > 9 void useAalter (A* pA);
    > 10 class B
    > 11 {
    > 12
    > 13 A m_a;
    > 14 public:
    > 15 B (A& a)
    > 16 {
    > 17 m_a = a;
    > 18 }
    > 19 A* getA () { return &m_a;}
    > 20 friend void useAalter(A*pA);


    This makes the function useAalter a friend. So far, so good.

    > 21 };
    > 22
    > 23 void useA (A* pA)
    > 24 {
    > 25 std::cout << pA->y << std::endl;
    > 26 }
    > 27
    > 28 void useAalter (A* pA)
    > 29 {
    > 30 std::cout << pA->y << std::endl;
    > 31 }
    > 32
    > 33 int main ()
    > 34 {
    > 35 A a = {45};
    > 36 B bInst (a);
    > 37 useA (bInst.getA());
    > 38 useAalter (&(bInst.m_a)) ;


    But here, you're getting an error because you're trying to resolve
    &(bInst.m_a), and pass that as an A*. But you're in main() here, not in
    useAalter() yet. The value you're trying to pass has to be resolved _here_,
    then passed as an A* parameter to useAalter(). And it can't be resolved
    here, because main() is not a friend of the class A.

    If you want to access the private member of bInst, you could make the
    parameter to useAalter() some kind of reference or pointer to a B instance,
    instead of a pointer to an A instance. Then you'd pass bInst (or its
    address) to useAalter(), instead of the address of bInst.m_a.

    -Howard
     
    Howard, Jun 29, 2006
    #2
    1. Advertising

  3. Ninan

    Kaz Kylheku Guest

    Ninan wrote:
    > When compiling using gcc 2.95.3, I get the following error for the
    > code snippet posted below.
    > bash-2.03$ g++ membAccess.C
    > membAccess.C: In function `int main()':
    > membAccess.C:13: `struct A B::m_a' is private
    > membAccess.C:38: within this context
    > Is this how it is supposed to work or is this a compiler specific issue
    >
    > 1 #include <iostream>
    > 2
    > 3
    > 4 struct A
    > 5 {
    > 6 int y;
    > 7 };
    > 8
    > 9 void useAalter (A* pA);
    > 10 class B
    > 11 {
    > 12
    > 13 A m_a;
    > 14 public:
    > 15 B (A& a)
    > 16 {
    > 17 m_a = a;
    > 18 }
    > 19 A* getA () { return &m_a;}
    > 20 friend void useAalter(A*pA);
    > 21 };


    Because useAalter is a friend of class B, it is allowed to access
    private members in that class.


    > 28 void useAalter (A* pA)
    > 29 {
    > 30 std::cout << pA->y << std::endl;
    > 31 }


    But useAalter does not actually access anything in class B. This
    function makes no use of its frienship to B whatsoever. It accesses the
    identifier A::y. This is allowed because y is public in struct A.

    > 32
    > 33 int main ()
    > 34 {
    > 35 A a = {45};
    > 36 B bInst (a);
    > 37 useA (bInst.getA());
    > 38 useAalter (&(bInst.m_a)) ;
    > 39 }


    Here, it is the function main which accesse the name B::m_a in line 38.
    Since main isn't a friend of the class B and m_a is private, this
    doesn't work.

    Access protection is concerned with name lookups, not pointer
    dereferences.

    The function useAalter has no idea that the A * which it is working
    with is in fact B::m_a. It could be any A struct whatsoever:

    A a = { 45 };

    useAalter(&a); // nothing to do with any B object
     
    Kaz Kylheku, Jun 29, 2006
    #3
  4. Ninan

    Yong Hu Guest

    Howard wrote:
    > "Ninan" <> wrote in message
    > news:...
    > > When compiling using gcc 2.95.3, I get the following error for the
    > > code snippet posted below.
    > > bash-2.03$ g++ membAccess.C
    > > membAccess.C: In function `int main()':
    > > membAccess.C:13: `struct A B::m_a' is private
    > > membAccess.C:38: within this context
    > > Is this how it is supposed to work or is this a compiler specific issue
    > >
    > > 1 #include <iostream>
    > > 2
    > > 3
    > > 4 struct A
    > > 5 {
    > > 6 int y;
    > > 7 };
    > > 8
    > > 9 void useAalter (A* pA);
    > > 10 class B
    > > 11 {
    > > 12
    > > 13 A m_a;
    > > 14 public:
    > > 15 B (A& a)
    > > 16 {
    > > 17 m_a = a;
    > > 18 }
    > > 19 A* getA () { return &m_a;}
    > > 20 friend void useAalter(A*pA);

    >
    > This makes the function useAalter a friend. So far, so good.
    >
    > > 21 };
    > > 22
    > > 23 void useA (A* pA)
    > > 24 {
    > > 25 std::cout << pA->y << std::endl;
    > > 26 }
    > > 27
    > > 28 void useAalter (A* pA)
    > > 29 {
    > > 30 std::cout << pA->y << std::endl;
    > > 31 }
    > > 32
    > > 33 int main ()
    > > 34 {
    > > 35 A a = {45};
    > > 36 B bInst (a);
    > > 37 useA (bInst.getA());
    > > 38 useAalter (&(bInst.m_a)) ;

    >
    > But here, you're getting an error because you're trying to resolve
    > &(bInst.m_a), and pass that as an A*. But you're in main() here, not in
    > useAalter() yet. The value you're trying to pass has to be resolved _here_,
    > then passed as an A* parameter to useAalter(). And it can't be resolved
    > here, because main() is not a friend of the class A.


    The error message "`struct A B::m_a' is private" is saying that main is
    not a friend of class B and thus class B's private member could not be
    accessed in main.

    >
    > If you want to access the private member of bInst, you could make the
    > parameter to useAalter() some kind of reference or pointer to a B instance,
    > instead of a pointer to an A instance. Then you'd pass bInst (or its
    > address) to useAalter(), instead of the address of bInst.m_a.
    >
    > -Howard
     
    Yong Hu, Jun 29, 2006
    #4
  5. Ninan

    Howard Guest

    "Yong Hu" <> wrote in message
    news:...
    >
    > Howard wrote:
    >> "Ninan" <> wrote in message
    >> news:...
    >> > When compiling using gcc 2.95.3, I get the following error for the
    >> > code snippet posted below.
    >> > bash-2.03$ g++ membAccess.C
    >> > membAccess.C: In function `int main()':
    >> > membAccess.C:13: `struct A B::m_a' is private
    >> > membAccess.C:38: within this context
    >> > Is this how it is supposed to work or is this a compiler specific issue
    >> >
    >> > 1 #include <iostream>
    >> > 2
    >> > 3
    >> > 4 struct A
    >> > 5 {
    >> > 6 int y;
    >> > 7 };
    >> > 8
    >> > 9 void useAalter (A* pA);
    >> > 10 class B
    >> > 11 {
    >> > 12
    >> > 13 A m_a;
    >> > 14 public:
    >> > 15 B (A& a)
    >> > 16 {
    >> > 17 m_a = a;
    >> > 18 }
    >> > 19 A* getA () { return &m_a;}
    >> > 20 friend void useAalter(A*pA);

    >>
    >> This makes the function useAalter a friend. So far, so good.
    >>
    >> > 21 };
    >> > 22
    >> > 23 void useA (A* pA)
    >> > 24 {
    >> > 25 std::cout << pA->y << std::endl;
    >> > 26 }
    >> > 27
    >> > 28 void useAalter (A* pA)
    >> > 29 {
    >> > 30 std::cout << pA->y << std::endl;
    >> > 31 }
    >> > 32
    >> > 33 int main ()
    >> > 34 {
    >> > 35 A a = {45};
    >> > 36 B bInst (a);
    >> > 37 useA (bInst.getA());
    >> > 38 useAalter (&(bInst.m_a)) ;

    >>
    >> But here, you're getting an error because you're trying to resolve
    >> &(bInst.m_a), and pass that as an A*. But you're in main() here, not in
    >> useAalter() yet. The value you're trying to pass has to be resolved
    >> _here_,
    >> then passed as an A* parameter to useAalter(). And it can't be resolved
    >> here, because main() is not a friend of the class A.

    >
    > The error message "`struct A B::m_a' is private" is saying that main is
    > not a friend of class B and thus class B's private member could not be
    > accessed in main.
    >


    Yeah, that's what I meant. I accidently said "not a friend of class _A_",
    when I mean "_B_".

    -Howard
     
    Howard, Jun 29, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Keith
    Replies:
    1
    Views:
    528
    Keith
    Feb 8, 2004
  2. Tristan
    Replies:
    1
    Views:
    431
    Hugo Pragt
    Jan 26, 2004
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,270
    Smokey Grindel
    Dec 2, 2006
  4. ankur
    Replies:
    1
    Views:
    13,072
    Jan =?UTF-8?B?VGhvbcOk?=
    Aug 27, 2007
  5. TheSouthLondonSlasher

    JUnit 4 Test Suite - addTest not applicable?

    TheSouthLondonSlasher, Sep 24, 2008, in forum: Java
    Replies:
    4
    Views:
    17,737
    Arne Vajhøj
    Oct 8, 2008
Loading...

Share This Page