LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Does making a class a 'friend' make the class' member classes 'friends'? (https://www.linuxquestions.org/questions/programming-9/does-making-a-class-a-friend-make-the-class-member-classes-friends-913757/)

Jusctsch 11-15-2011 11:24 PM

Does making a class a 'friend' make the class' member classes 'friends'?
 
Based on previous compiles of my particular code, I would assume yes, but I've been fighting an issue where I keep getting privacy errors in this case.

Code:

class Cat;

class Vase
{

  private:
      friend class Cat;
      void smash();
};

class Cat
{
  private:
  class Tail
  {
      void wag(Vase *a){ a->smash();}
  };
};

Would this be the error as follows?:

error: `void Vase::smash()' is private

If that doesn't work, what should be done?

Thanks

firstfire 11-16-2011 12:24 AM

Hi.

Maybe you should put 'public:' just before 'void wag(...)'?
Code:

#include <iostream>
using namespace std;

class Cat;

class Vase
{

  private:
      friend class Cat;
      void smash(){ cout << "smash" << endl; };
};

class Cat
{
  public:
  Cat()
  {
        Tail t;
        Vase v;
        t.wag(&v);
  }
  private:
  class Tail
  {
    public:
      void wag(Vase *a){ a->smash(); }
  };
};
int main()
{
        Cat c;
        return 0;
}

This code compiles fine and prints 'smash', thus private function Vase::smash() is available inside Tail class.

corp769 11-16-2011 12:31 AM

Before, I really wanted to reply with the following, without even fully looking at the code:
"Just make it public."

Guess I was right :p

SigTerm 11-16-2011 12:51 AM

Quote:

Originally Posted by Jusctsch (Post 4525137)
Does making a class a 'friend' make the class' member classes 'friends'?

No.
Quote:

Originally Posted by C++Standard
ISO/IEC 14882:2003
11.4 [class.friend]
...
Declaring a class to be a friend implies that the names of private and protected members from the class
granting friendship can be accessed in declarations of members of the befriended class. [Note: this means
that access to private and protected names is also granted to member functions of the friend class (as if the
functions were each friends) and to the static data member definitions of the friend class. This also means
that private and protected type names from the class granting friendship can be used in the base-clause of a
nested class of the friend class. However, the declarations of members of classes nested within the friend
class cannot access the names of private and protected members from the class granting friendship.
Also,
because the base-clause of the friend class is not part of its member declarations, the base-clause of the
friend class cannot access the names of the private and protected members from the class granting friend-
ship. For example,

Quote:

Originally Posted by Jusctsch (Post 4525137)
Based on previous compiles of my particular code, I would assume yes, but I've been fighting an issue where I keep getting privacy errors in this case.

You should use "friend" only when absolutely necessary. Your example doesn't need "friends". You also don't need private functions in this particular case.

firstfire 11-16-2011 04:24 AM

Just found this thread. As I understand, there are no single opinion about this problem in C++ standard currently in use, but newer standard C++0X seems to allow that access.

SigTerm 11-16-2011 04:31 AM

Quote:

Originally Posted by firstfire (Post 4525377)
Just found this thread. As I understand, there are no single opinion about this problem in C++ standard currently in use, but newer standard C++0X seems to allow that access.

  1. The quote I provided is from 2003 standard.
  2. There's no "standard currently in use". Different compiler may support different standard. There is, however, most recent standard.
  3. C++0x is a draft. The proper name for most recent standard is C++11.

Jusctsch 11-16-2011 09:31 AM

Quote:

Originally Posted by SigTerm (Post 4525382)
  1. The quote I provided is from 2003 standard.
  2. There's no "standard currently in use". Different compiler may support different standard. There is, however, most recent standard.
  3. C++0x is a draft. The proper name for most recent standard is C++11.

I've seen different behavior on different compilers unfortunately.
Code:

class Cat;

class Vase
{

  private:
      friend class Cat;
      friend class Cat::Tail;
      void smash();
};

class Cat
{
  private:
  class Tail
  {
      private:
      void wag(Vase *a){ a->smash();}
  };
};

Couldn't this also be a legal statement? I'm not a fan of opening gaping holes when a small peephole would work just fine.
Side topic, but is 'friend' perceived as being a huge hack in C++?

EDIT
Code:

#include <iostream>
using namespace std;

class Cat;

class Vase
{

  private:
      friend class Cat;
      void smash(){ cout << "smash" << endl; };
};

class Cat
{
  public:
  Cat()
  {
        Tail t;
        Vase v;
        t.dostuff(&v);
  }
  private:
  class Tail
  {
      public:
          void dostuff(Vase *a){wag(a);}
      private:
      void wag(Vase *a){ a->smash(); }
  };
};
int main()
{
        Cat c;
        return 0;
}

This compiles legally. On running the resulting binary, the member Tail is able to 'smash' the Vase. The member (Tail) is calling the private function of the class (Vase) who had friended the parent class (Cat).

Quote:

$ g++ --version
g++.exe (GCC) 4.4.3
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ friends_who_have_member_classes.cpp -o test

$ ./test
smash
Is this what people would expect?

sundialsvcs 11-17-2011 07:58 PM

My not-so-good anymore eyes (shaddup... it will happen to you, too!) are starting to glaze-over here.

If you're starting to write code that ventures into this kind of esoterica in the definition (past or present or future) of the C++ language ...

... then you need to be advised from the outset that "you are in the process of making what will one day be regarded as a package of unmaintainable sh*t." :eek:

Please, hear me out.

If there are but two things that are absolute constants in the world of software, they are these:
  1. Businesses change.
  2. Software doesn't.
It would probably be more accurate to say that, since at the end of the day the software in question m-u-s-t somehow be caused to match the business (the software is, after all, much too expensive and much too business-critical to throw away ...), "it will be dragged, kicking and screaming, across the transom of change," and it will probably fall completely apart in the process.

When you are writing software... "please, don't be clever." Every time you avail yourself of features such as "friends," you are (whether you realize the long-term implications of your actions or not ...) creating a wicked and utterly intractable functional dependency between the two that one day just might be regarded as the relationship between Harry Potter and Lord Voldemort.

I'll step off my soapbox now. But please, mark my words. I've spent most of my thirty-plus year career untangling what was once "clever" software. And sometimes it feels just like disarming a most-delicate bomb. The most noble of intentions, practiced by obviously skilled and knowledgeable programmers, can nevertheless turn into ... scrap. And, if I may bluntly say so, "the more 'clever' it is, the more likely it is to be unsalvageable." :jawa: (And let no one call me a Luddite, because you would not know whereof you speak. Just sayin' ...)

The guy who runs the junk-yard does have a valid opinion with regard to cars.


All times are GMT -5. The time now is 06:15 AM.