Suppose we have two classes:
class Base
{
private:
int x;
public:
void f();
};
class Foo
{
// some variables and methods
};
Now everyone can call Base::f()
, but I want only Foo
to be able to do so.
In order to achieve this effect, we can make Base::f()
private and declare Foo
as a friend:
class Base
{
private:
int x;
void f();
friend Foo;
};
The problem with this approach is that Foo
has the access to both Base::f()
and Base::x
(and even to any other private members of Base
). But I want Foo
to have access only to Base::f()
.
Is there a way for a class (or a function) to grant an access only to certain private members of another class? Or maybe anyone could suggest a better approach to my problem?
EDIT:
I'll try to specify the access restriction I need. Firstly, Base
is an interface in a library (it's an abstract class, in fact). The user uses only the classes derived from Base
. Base::f()
is called only by Foo
which is another class in the library. Hiding Base::f()
from the user is important, because only Foo
knows when to call it. At the same time, Foo
shouldn't mess up the other members of Base
.
Very hacky, but this will allow very fine grained access.
class Base
{
private:
int x;
void f();
friend class Base_f_Accessor;
};
class Base_f_Accessor
{
private:
static void f(Base & b) { b.f(); }
friend class Foo;
}
class Foo
{
// some variables and methods
};
You can create another class that contains the data for Base
like this:
class BaseData {
protected:
int x;
};
class Base : public BaseData {
friend class Foo;
void f ();
};
Now, Foo
can access f
as a method of Base
like you wanted, but not x
. Friendship is not commutative. By using protected
, x
appears private to everyone except those that derived directly from BaseData
.
A better approach might be to use multiple inheritance to define Base
, and provide Foo
access only to those classes you want from which Base
derives.
class With_f {
friend class Foo;
protected:
virtual void f () = 0;
};
class With_g {
protected:
virtual void g () = 0;
};
class Base : public With_f, public With_g {
int x;
void f () {}
void g () {}
};
Here, Foo
would have to have a With_f
pointer to Base
, but it could then access the f
method. Foo
could not access g
.
There's no easy, non-hackish way to achieve that. C++ simply doesn't have such access control granularity. You can play with some inheritance, but increased complexity outweighs any advantages this access restriction might have. Also, this approach doesn't scale - you can grant increased permissions only to one friend class.
Maybe a bit cumbersome, but you could make nested classes where the nesting class is friend, then you can add friends per nested class. This gives some level of granularity:
#include <iostream>
class Nesting
{
friend class Foo;
class Nested1
{
friend class Nesting;
public:
Nested1() : i(3) { }
private:
int i;
} n1;
class Nested2
{
friend class Nesting;
friend class Foo;
public:
Nested2() : j(5) { }
private:
int j;
} n2;
int f() { return n1.i; }
};
class Foo
{
public:
Foo(Nesting& n1) : n(n1) { }
int getJ() { return n.n2.j + n.f(); }
private:
Nesting& n;
};
int main()
{
Nesting n;
Foo foo(n);
std::cout << foo.getJ() << "\n";
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.