1

I have class A and class B. class A has a bunch of variables with gets/sets, but I only want those sets to be called from class B. The only way I can think of doing this is making the sets protected, and deriving class B from class A. But then class B would end up inheriting a bunch of unnecessary stuff from class A.

Example:

class A {
public:
void setHealth();
int getHealth();

private:
int health;
};

class B {
public:
void someMethod() { classAInstance.setHealth(); } //This should work

private:
A classAInstance;

};

A classAInstance;
classAInstance.setHealth(); //This should not work because its not being called from Class B

I hope I explained my question enough for you to udnerstand what I need. Thanks in advance!

Brad
  • 10,015
  • 17
  • 54
  • 77
  • 2
    Have a look at the passkey idiom: http://stackoverflow.com/questions/6545490/how-can-i-check-a-function-was-called-by-another-function/6545585#6545585 – Xeo Jan 02 '12 at 23:57
  • 1
    Consult your favorite C++ language book about the *friend* keyword. – Hans Passant Jan 02 '12 at 23:59

4 Answers4

3

You could declare the setters as protected or private, and then declare B to be a friend of A:

class A {
    friend class B;

    ...
};

See the C++ FAQ for more details: http://www.parashift.com/c++-faq-lite/friends.html.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • The trouble with friends: Now, the getters and setters don't need to be called anymore and the variables can be accessed directly. – pmr Jan 03 '12 at 00:01
  • @pmr then just make the variables private, the getters/setters protected, and friend B in protected scope? – Tom Knapen Jan 03 '12 at 00:02
  • 3
    @Tom: huh? `friend` gives access to `private` members, doesn't matter where you put the `friend` declaration. – Ben Voigt Jan 03 '12 at 00:03
  • @TomKnapen I did not know that access specifiers change the semantics of `friends` and can find no reference to this. Could you show me one? – pmr Jan 03 '12 at 00:04
  • @BenVoigt I'm sorry, I've always been doing things that way, but never tested it in this manner. I've ran a quick test and now I see the access specifiers don't change any semantics. Therefore I apologise, and would like to ask you to ignore my previous comment :) – Tom Knapen Jan 03 '12 at 00:12
1

If you want all access to A to go through B and enforce that B does not access private data without going through the set-/get- member functions of A... you could do something like this (even though it's unnecessarily complicated):

class A
{
  friend class B;
  void setValue(const int &value) { aData.x = value; }
  int getValue() const { return aData.x; }
  class AData
  {
    friend class A;
    int x;
  };
  AData aData;
};

class B
{
public:
  int getValue() const { return a.getValue(); }
  void setValue(const int &value) { a.setValue(value); }

private:
  A a;
};
cstream
  • 139
  • 1
0

You can make the class B a friend of A:

class B;
class A {
    friend class B;
    // ...
};
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

Make B a friend of A, thus allowing it to access A's private (and protected) members:

class A {
    friend class B;
}
Tamer Shlash
  • 9,314
  • 5
  • 44
  • 82