Suppose I have three C++ classes FooA, FooB and FooC.
FooA has an member function named Hello
, I want to call this function in class FooB, but I don\'t
The whole idea of friend
is to expose your class to a friend.
There are 2 ways you could be more specific about what you expose:
Inherit from FooA
, that way only protected and public methods are exposed.
Only befriend a certain method, that way only that method will have access:
.
friend void FooB::fun();
The safest solution is to use another class as the "go-between" for your two classes, rather than make one of them a friend.
One way to do this is suggested in the answer by @ForEveR, but you can also do some searching about proxy classes and other design patterns that can apply.
There's nothing to make a class a friend of one specific function, but you can make FooB
a friend of a "key" class with private constructor, and then have FooA::Hello
take that class as an ignored parameter. FooC
will be unable to provide the parameter and hence can't call Hello
:
Is this key-oriented access-protection pattern a known idiom?
No, and this is not really a limitation. To my mind, the limitation is that friend
— a blunt weapon for hacking around design flaws — exists in the first place.
Your class FooA
has no business knowing about FooB
and FooC
and "which one should be able to use it". It should have a public interface, and not care who can use it. That's the point of the interface! Calling functions within that interface should always leave the FooA
in a nice, safe, happy, consistent state.
And if your concern is that you might accidentally use the FooA
interface from somewhere you didn't mean to, well, simply don't do that; C++ is not a language suited to protecting against these kinds of user errors. Your test coverage should suffice in this case.
Strictly speaking, I'm sure you can obtain the functionality you're after with some ghastly complicated "design pattern" but, honestly, I wouldn't bother.
If this is a problem for the semantics of your program's design, then I politely suggest that your design has a flaw.
You'll need inheritance. Try this:
// _ClassA.h
class _ClassA
{
friend class ClassA;
private:
//all your private methods here, accessible only from ClassA and _ClassA.
}
// ClassA.h
class ClassA: _ClassA
{
friend class ClassB;
private:
//all_your_methods
}
This way you have:
ClassB
is the only one to be able to use ClassA
.
ClassB
cannot access _ClassA
methods, that are private.
You can partially expose a class's interfaces to a specified client by inherit it from an interface class.
class FooA_for_FooB
{
public:
virtual void Hello() = 0;
virtual void Hello2() = 0;
};
class FooA : public FooA_for_FooB
{
private: /* make them private */
void Hello() override;
void Hello2() override;
private:
void Hello3();
int m_iData;
};
class FooB
{
void fun()
{
FooA objA;
FooA_for_FooB &r = objA;
r.Hello() // right
r.Hello2() // right
objA.Hello3() // compile error
objA.m_iData = 0; // compile error
}
};
class FooC
{
void fun()
{
FooA objA;
objA.Hello() // compile error
objA.Hello2() // compile error
objA.Hello3() // compile error
objA.m_iData = 0; // compile error
}
};
Here access control is enhanced by the base class FooA_for_FooB
. By a reference of type FooA_for_FooB
, FooB
can access the members defined within FooA_for_FooB
. However, FooC
cannot access those members since they have been override as private members in FooA
. Your purpose can be achieved by not using the type FooA_for_FooB
within FooC
, or any other places except FooB
, which can be kept without paying much attention.
This approach needs no friend
, making things simple.
A similar thing can be done by making everything private in a base class, and selectively wrap-and-expose some of the members as public in the derived class. This approach may sometimes require ugly downcast, though. (Because the base class will become the "currency" among the whole program.)