Разрешить доступ класса для одного частного члена
У меня есть класс A, который имеет закрытый метод, называемый (). У меня также есть класс B, которому требуется доступ к a () (но только B должен иметь доступ к a (), поэтому a () является приватным). Теперь я мог бы использовать спецификатор друга, но это сделало бы другие частные методы A (давайте назовем их b () и c ()) также доступными для B, и я не хочу такого поведения.
Есть ли способ сделать только () из A доступным для B?
4 ответа
Нет, нет, но, как вы укажете точный класс, только B может получить доступ к закрытым членам A. Вам просто нужно позаботиться о том, какой метод вызывается.
Поскольку дружеские отношения не наследуются, вам не нужно беспокоиться о возможных подклассах B.
Есть способ - если у вашего класса есть публичная функция шаблона:
class A {
// apparently private
void priv () { std::cout << "got you A::a()" << std::endl ; }
public:
template <class T>
void abuse() {}
};
struct Thief {};
template <>
void A::abuse<Thief>() {
this->priv();
}
int main() {
A a;
// obviously do not compile : a.priv();
// this i OK
a.abuse<Thief>();
return 0;
}
Должен признаться, я украл это у GotW...
Да, у меня есть простой способ. Пусть B имеет указатель на A::a(), вот так:
typedef boost::function<void ()> functype;
class A {
private:
void a();
};
class B {
public:
void setfp(functype f) {m_f = f;}
void foo() {
// do some stuff
m_f();
}
private:
functype m_f;
};
A a;
B b;
b.setfp(boost::bind(&A::a, &a));
b.foo();
Это может быть сделано с некоторым "поворотом".
Просто выделите метод a() из класса A в родительский класс, в котором B является классом-другом, и пусть A наследует его. это оставит a() как метод в A, но единственный приватный метод, доступный другу его родителя B.
Вот очень простой код, чтобы уточнить, что я сказал:
class parent
{
friend class B;
private:
void a() {}
};
class A:public parent
{
private:
void b() {}
void c() {}
};
class B
{
A* m_a;
public :
B()
{
m_a = new A();
m_a->a(); // OK
m_a->b(); // error C2248: 'A::b' : cannot access private member declared in class 'A'
}
};
Надеюсь, поможет!