Partial accessibility to a class's interface

A

Andy Venikov

Hi all,

is there a way to make certain functions of a
class be accessible only by specific class?
Like "friend class whatever", but only for a few
functions?

This could be usefull in a following relationship:

Client
/ \
/ \
use/ \use
/ \
Managed Object<---->Object Manager


Lets say I have a class Widget.
I also have a manager for that class, called
WidgetManager. Widget is accessed by both a client and
a widget manager. Client shouldn't be able to access functions
used only by a WidgetManager. But I don't want to make
WidgetManager a friend of Widget because I want to hide
implementation details of the Widget from WidgetManager.

Is there a trick to do that?

Thanks,
Andy.
 
V

Victor Bazarov

Andy said:
is there a way to make certain functions of a
class be accessible only by specific class?

Extract those functions in a separate class, derive from it,
and let the "specific class" be a friend of the base class.
Like "friend class whatever", but only for a few
functions?

This could be usefull in a following relationship:

Client
/ \
/ \
use/ \use
/ \
Managed Object<---->Object Manager


Lets say I have a class Widget.
I also have a manager for that class, called
WidgetManager. Widget is accessed by both a client and
a widget manager. Client shouldn't be able to access functions
used only by a WidgetManager. But I don't want to make
WidgetManager a friend of Widget because I want to hide
implementation details of the Widget from WidgetManager.

Is there a trick to do that?

Using the proposed scheme, you should get

class ManagedWidget {
friend class WidgetManager;
void do_manage(); // whatever that means...
};

class MyWidget : public ManagedWidget {
void do_some_other_stuff(); // hidden implementation details
public:
void do_client_stuff();
};

class WidgetManager {
...
void manage_a_widget(ManagedWidget &mw) {
mw.do_manage();
}
};

Victor
 
A

Andy Venikov

Extract those functions in a separate class, derive from it,
and let the "specific class" be a friend of the base class.

class ManagedWidget {
friend class WidgetManager;
void do_manage(); // whatever that means...
};

class MyWidget : public ManagedWidget {
void do_some_other_stuff(); // hidden implementation details
public:
void do_client_stuff();
};

class WidgetManager {
...
void manage_a_widget(ManagedWidget &mw) {
mw.do_manage();
}
};

Victor

I see. Thanks.

But there's a problem with this solution. ManagedWidget exposes
everything to the WidgetManager
and if do_manage wants to operate with some private data (which would
always be the case) then that
private data would be accessible by WidgetManager as well.
Unless, unless we made do_manage() a virtual function and defined all
private data in MyWidget.
But that forces us to do a virtual call where it wasn't necessary
before.
Plus, what if I want to restrict client's interface only to a client?
Client part of the Widget's interface
may make sense only to clients, not to managers.

I guess in that case we could use "my firend's friend is not my
friend" thing and have a common base
structure with everything a widget needs to know.
Like this:

struct WidgetBase
{
private:
//define all widget's gadgets

friend class ManagedWidget;
friend class MyWidget;
friend class AccessedWidget
};

class ManagedWidget : virtual WidgetBase
{
friend class WidgetManager

//Specify interface for WidgetManager
void do_manage()
{
//Now we can access all gadgets, which are private in this context
}
};

class AccessedWidget : virtual WidgetBase
{
friend class Client;

//Specify client's interface
void do_client_stuff()
{
//we still can access all the gadgets from here, because we're
friends with WidgetBase
}
};

class MyWidget : ManagedWidget, AccessedWidget
{
public:
void do_something_visible_to_everyone()
{
//we still can access all the gadgets from here, because we're
friends with WidgetBase
}
};


That seems to work, or am I missing something?

Thanks,
Andy.
 
K

Karl Heinz Buchegger

Andy said:
I see. Thanks.

But there's a problem with this solution. ManagedWidget exposes
everything to the WidgetManager
and if do_manage wants to operate with some private data (which would
always be the case) then that
private data would be accessible by WidgetManager as well.
Unless, unless we made do_manage() a virtual function and defined all
private data in MyWidget.
But that forces us to do a virtual call where it wasn't necessary
before.

That's the price you have to pay.
On the other hand the class names suggest that you are dealing
with some GUI elements. Does it really matter that much to spend
0.0000001 seconds in a virtual function call, when the user will
never notice this delay?

[snip code which has a lot of friend definitions]

I wouldn't do it that way.
That's too much trouble in the long run just to eliminate
a virtual function call.
 
J

Jerry Coffin

Hi all,

is there a way to make certain functions of a
class be accessible only by specific class?
Like "friend class whatever", but only for a few
functions?

No. To me, the fact that you want to indicates that the class in
question probably isn't very well designed -- specifically it sounds
like it has a number of basically unrelated responsibilities.

[ ... ]
Lets say I have a class Widget.
I also have a manager for that class, called
WidgetManager. Widget is accessed by both a client and
a widget manager. Client shouldn't be able to access functions
used only by a WidgetManager. But I don't want to make
WidgetManager a friend of Widget because I want to hide
implementation details of the Widget from WidgetManager.

One possibility would be to use multiple inheritance:

class UI_object {
};

class managed_object {
};

class widget : public managed_object, public UI_object {
// actual implementation of a manageable widget.
};

With this scheme, the manager works with managed objects, and the
client works with UI objects. A widget is both, but code that works
with one of the base classes only sees the part that it needs to.

With this scheme, it's fairly common (though not necessary) for the
base classes to be composed primarily (or exclusively) of pure virtual
function declarations -- I.e. defining only an interface, not any
implementation.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top