C++ 允许“朋友”类仅访问某些私有成员
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16055616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Allowing a "friend" class to access only some private members
提问by Archer
Suppose I have three C++ classes FooA, FooB and FooC.
假设我有三个 C++ 类 FooA、FooB 和 FooC。
FooA has an member function named Hello
, I want to call this function in class FooB, but I don't want class FooC be able to call it. The best way I can figure out to realize this is to declare FooB as a friend class of FooA. But as long as I do this, allFooA's private and protected members will be exposed which is quite unacceptable to me.
FooA 有一个名为 的成员函数Hello
,我想在类 FooB 中调用此函数,但我不希望类 FooC 能够调用它。我能想出实现这一点的最好方法是将 FooB 声明为 FooA 的朋友类。但是只要我这样做,所有FooA 的私有成员和受保护成员都会暴露出来,这对我来说是非常不可接受的。
So, I wanna know if there is any mechanism in C++(03 or 11) better than friend
class which can solve this dilemma.
所以,我想知道 C++(03 或 11)中是否有比friend
类更好的机制可以解决这个难题。
And I assume it will be nice if the following syntax is possible:
我认为如果可以使用以下语法会很好:
class FooA
{
private friend class FooB:
void Hello();
void Hello2();
private:
void Hello3();
int m_iData;
};
class FooB
{
void fun()
{
FooA objA;
objA.Hello() // right
objA.Hello2() // right
objA.Hello3() // compile error
ojbA.m_iData = 0; // compile error
}
};
class FooC
{
void fun()
{
FooA objA;
objA.Hello() // compile error
objA.Hello2() // compile error
objA.Hello3() // compile error
ojbA.m_iData = 0; // compile error
}
};
采纳答案by Steve Jessop
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
:
没有什么可以让一个类成为一个特定函数的朋友,但是你可以让FooB
一个带有私有构造函数的“关键”类成为朋友,然后FooA::Hello
将该类作为一个被忽略的参数。FooC
将无法提供参数,因此无法调用Hello
:
Is this key-oriented access-protection pattern a known idiom?
回答by ForEveR
I think you can use Attorney-Clienthere.
我认为您可以在这里使用“律师-客户”。
In your case example should be like this
在你的情况下,例子应该是这样的
class FooA
{
private:
void Hello();
void Hello2();
void Hello3();
int m_iData;
friend class Client;
};
class Client
{
private:
static void Hello(FooA& obj)
{
obj.Hello();
}
static void Hello2(FooA& obj)
{
obj.Hello2();
}
friend class FooB;
};
class FooB
{
void fun()
{
FooA objA;
Client::Hello(objA); // right
Client::Hello2(objA); // right
//objA.Hello3() // compile error
//ojbA.m_iData = 0; // compile error
}
};
class FooC
{
void fun()
{
/*FooA objA;
objA.Hello() // compile error
objA.Hello2() // compile error
objA.Hello3() // compile error
ojbA.m_iData = 0; // compile error*/
}
};
回答by Lightness Races in Orbit
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.
不,这并不是真正的限制。在我看来,局限性在于friend
——一种绕过设计缺陷的钝器——首先存在。
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 carewho can use it. That's the point of the interface! Calling functions within that interface should alwaysleave the FooA
in a nice, safe, happy, consistent state.
你的类FooA
没有业务寂寂FooB
和FooC
和“这应该能够使用它。” 它应该有一个公共接口,而不关心谁可以使用它。这就是界面的重点!该界面中调用函数应该始终保留FooA
在一个不错的,安全的,幸福的,一致的状态。
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.
如果您担心您可能会在无意中意外使用该FooA
界面,那么请不要这样做;C++ 不是一种适合防止此类用户错误的语言。在这种情况下,您的测试覆盖率应该足够了。
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.
如果这是您程序设计语义的问题,那么我礼貌地建议您的设计存在缺陷。
回答by Jerome Baldridge
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.
最安全的解决方案是使用另一个类作为两个类的“friend.
中间人”,而不是让其中一个成为@ForEveR 的答案中建议的一种方法,但您也可以对代理进行一些搜索类和其他可以应用的设计模式。
回答by rolevax
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.
在这里,基类增强了访问控制FooA_for_FooB
。通过引用类型FooA_for_FooB
,FooB
可以访问其中定义的成员FooA_for_FooB
。但是,FooC
无法访问这些成员,因为它们已在FooA
. 你的目标可以通过不使用类型来实现FooA_for_FooB
内FooC
,或任何其他地方,除了FooB
,这可以保持不十分重视。
This approach needs no friend
, making things simple.
这种方法不需要friend
,使事情变得简单。
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.)
类似的事情可以通过将基类中的所有内容设为私有,并有选择地将派生类中的某些成员包装并公开为公共成员来完成。但是,这种方法有时可能需要丑陋的沮丧。(因为基类会成为整个程序中的“货币”。)
回答by user3737631
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.
这样您就拥有:
ClassB
是唯一能够使用ClassA
.
ClassB
无法访问_ClassA
私有的方法。
回答by Yochai Timmer
The whole idea of friend
is to expose your class to a friend.
整个想法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:
继承自
FooA
,这样只会公开受保护和公共方法。只与某个方法成为朋友,这样只有那个方法才能访问:
.
.
friend void FooB::fun();