views:

966

answers:

10
+3  Q: 

c++ class friend

Hi, I'm trying to compile such code:

#include <iostream>
using namespace std;

class CPosition
{
  private:
    int itsX,itsY;
  public:
    void Show();
    void Set(int,int);
};

void CPosition::Set(int a, int b)
{
  itsX=a;
  itsY=b;
}

void CPosition::Show()
{
    cout << "x:" << itsX << " y:" << itsY << endl;
}

class CCube
{
  friend class CPosition;
  private:
         CPosition Position;
};

main()
{
  CCube cube1;

  cube1.Position.Show();
  cube1.Position.Set(2,3);
  cube1.Position.Show();
}

but get 'CCube::Position' is not accessible in function main() 3 times. I want class CPosition to be declared outside CCube so that I can use it in future in new classes e.g. CBall :) but how can I make it work without using inheritance. Is it possible :)?

Regards, PK

+1  A: 

errr, no, Position isnt visible in the function "main"

Make it public... or put a public getter function in

Keith Nicholas
+4  A: 

The statement friend class CPosition; means that CPosition can now access the private members of the CCube class. To every other class the members are still as private as you declared them. To make the sample work you'd:

class CCube
{
     public:
         CPosition Position;
};
Jasper Bekkers
A: 

And if I don't want to make it public? :) I've tried making a method:

CPosition GetPos() {return Position;};

but it works only with Show(), and not with Set(x,y) - still a problem.

Moomin
You're returning a copy, so Set will work, but on the copy, return a reference to update it
Pieter
A: 

Well, you already got an answer for the error. One things though: Do you plan on having the cube access the private members of CPosition (itsX, itsY)? If not, it doesn't need to be declared as a friend. If it is, consider exposing public methods in CPosition to return X and Y, and you still don't need to declare it as a friend.

What I'm saying is that you need to make sure that you need to use friends. Here's a good place to start.

Firas Assaad
+1  A: 

Your friend declaration would need to be

friend int main();

You are giving 'main' permission to access CCube's private member.

James Hopkin
A: 

Ok, but isn't making it public a little dangerous while writing large projects? Is there any other way to get clear line like Object."Property("subobject")".Action()?

Moomin
You could always write functions like setPosition, getX, getY in CCube to completely hide the position property. You could also do what Pieter said and return a reference to the position: CPosition } then do cube1.getPosition.set(1, 2)
Firas Assaad
A: 

OK it works with:

class CCube
{
  private:
         CPosition Position;
  public:
  CPosition& getPosition() { return Position; }
};

main()
{
  CCube cube1;

  cube1.getPosition().Show();
  cube1.getPosition().Set(2,3);
  cube1.getPosition().Show();
}

Thanks

Moomin
This certainly works, that doesn't mean it's the best idea though. It might be better to e.g. add a SetPosition(x, y) in CCube that call Position.Set(x, y) itself, that way you're hiding the internals of CCube better. Essentially adding public functions for the parts of Position you want accessible.
Pieter
A: 

You have 3 questions in one:

  1. reusability of CPosition
  2. how to influence a shape's state (in this case includes a member of type CPosition, but may also include an int radius or something else)
  3. Usage of the friend keyword

You clearly say you need the CPosition class to be accessible from other places. Well, it is class. Problem 1 is solved.

If you want you CCube users to be able to change a CCube's position, you need to provide a means for that:

  1. By making CCube::Position public
  2. By adding accessor methods - CCube::MoveTo( const CPosition& p ) and CCube::GetPosition() const.

As @Firas said: don't play with friend until you're really sure you need it.

xtofl
+4  A: 

In addition to the normal getter you should also have a const getter.
Please note the return by reference. This allows you any call to SetXX() to affect the copy of Position inside CCube and not the copy that you have been updating.

class CCube
{
    private:
        CPosition Position;
    public:
        CPosition&       getPosition()       { return Position; }
        CPosition const& getPosition() const { return Position; }
};
Martin York
A: 

Nice, but what const getter do?

Moomin
It means that if someone has a const CCube, they can call "getPosition" on it, and get back a const Position. If there's no const getter, then someone with a const CCube can't read the Position. By rights they should be able to. The Show method on CPosition should be const for the same reason.
Steve Jessop
Note that it's important that the const version of getPosition return a const CPosition. Otherwise someone could call Set on it, and change the position of a const CCube. That's not what you want: you want Show and Set for non-const objects, but only Show for const ones.
Steve Jessop