3

Possible Duplicate:
What are access specifiers? Should I inherit with private, protected or public?

I am looking for some code or design pattern to grant access to a private method from another class (C++).

Let's say I have 1 class OBJ1 :

class OBJ1
{
  public:
    void method1();
    void method2();
}

And another class OBJ2, which instantiate OBJ1 :

class OBJ2
{
  public:
    void method3()
    {
       my_obj.method1();
    }
  private:
    OBJ1 my_obj;
}

Is there a way to access OBJ2::my_obj.method2() from other classes (this method only) ?

Community
  • 1
  • 1
Patouf
  • 119
  • 4
  • 15

5 Answers5

2

Accessing method2 is possible, because it's public. Accessing the member my_obj can't be done directly because it's private. To grant other classes access to it, declare them as friend in OBJ2.

class OBJ2
{
  public:
    void method3()
    {
       my_obj.method1();
    }
  private:
    friend class X;
    OBJ1 my_obj;
}

Now, X can access OBJ2::my_obj.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 1
    But that opens up all operations on `my_obj`, not only `method2`. – Daniel Earwicker Oct 02 '12 at 13:14
  • @DanielEarwicker all operations on `my_obj` are already open... they're all public. – Luchian Grigore Oct 02 '12 at 13:15
  • 2
    @LuchianGrigore `my_obj` is a private attribute of OBJ2, so `friend` does not solve my problem here. I want to know if there's a way to access `OBJ2::my_obj.method2()` (not `OBJ1::method2()`) **only**. :) – Patouf Oct 02 '12 at 13:23
  • @Patouf it does. `X` can now access `OBJ2::my_obj`. Read my answer again. – Luchian Grigore Oct 02 '12 at 13:26
  • 3
    His comment "(this method only)" implies that he doesn't want unlimited access to `my_obj` from X. He only wants to be able to call `method2` from outside of the class. – mwigdahl Oct 02 '12 at 13:29
1

Probably the best way to do this would be to provide a public passthrough function for this specific function, something like you did for method3:

class OBJ2 
{   
     public:
         void method3()     
         {
             my_obj.method1();
         }
         void method2()
         {
             my_obj.method2();
         }
     private:
         OBJ1 my_obj; 
} 

This changes the syntax slightly -- you're calling the method against an OBJ2 instance rather than directly against the contained OBJ1 instance, but the effect will be what you asked for.

One other consideration here is that this type of idiom (public wrapper functions) gives unlimited external access to a single function of your contained member. The other approach (friend declarations) gives a single external class access to the entirety of your private internals. If what you want is to grant a single external class access to a single member, you might be better off combining these approaches using a proxy object or something of the sort.

mwigdahl
  • 16,268
  • 7
  • 50
  • 64
1

You've answered your own question: look at method3, which provides a way to call method1 on my_obj via the enclosing class OBJ2. A similar forwarding method could be added to allow access to method2.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
  • I'll try this, it should work. And you're right, I actually answered my own question... Thanks ! – Patouf Oct 02 '12 at 13:29
0

What you need is a public method in OBJ2 that calls method2 on the my_obj member.

In this case friendship won't help you because it would grant access to all of my_obj.

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

From the design point of view, the language does not provide facilities to control per-member access, and while you can hack that in it is just going to make the code more convoluted, harder to maintain and to manage for the compiler (more complex code means harder to optimize code).

Some alternatives if that member is really different to the rest and objects accessing it shall not access the rest of the object would include defining an interface (polymorphic) and implementing that interface in OBJ1. Then you can hand a reference to that interface that has no other members available.

From a technical point of view there are multiple things that can be done, for example you can create an accessor function object that takes an OBJ1 as parameter and calls the method. The functor would have to be a friend of OBJ1 (assume all other members are private), operator() (or a named function that performs the dispatch, and make that private) and then befriend OBJ2 from that intermediate dispatcher.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489