什么时候应该在C ++中使用“朋友”?
我一直在阅读C ++常见问题,并对friend
声明感到好奇。 我个人从未使用过它,但我有兴趣探索这种语言。
什么是使用friend
的好例子?
再读一遍FAQ,我喜欢<<
>>
操作符重载并添加为这些类的朋友的想法。 但我不知道这是如何不破坏封装。 什么时候这些例外可以保持在OOP的严格范围内?
首先(IMO)不要听那些说friend
没用的人。 它是有益的。 在很多情况下,您将拥有不具有公开可用数据或功能的对象。 对于许多作者而言,这可能只是表面上熟悉不同领域的大型代码库尤其如此。
除了朋友说明符以外,还有其他替代方法,但通常它们很麻烦(cpp-level具体类/ masked typedef)或者不是万无一失(注释或函数名称约定)。
在答案上;
friend
说明符允许指定的类访问受保护的数据或类中的功能,从而生成好友语句。 例如,在下面的代码中,任何人都可以向孩子询问他们的姓名,但只有母亲和孩子可以更改姓名。
您可以进一步考虑更复杂的类,如窗口,这个简单的例子。 很有可能一个窗口将有许多功能/数据元素不应公开访问,但是相关类(如WindowManager)需要这些元素。
class Child
{
//Mother class members can access the private parts of class Child.
friend class Mother;
public:
string name( void );
protected:
void setName( string newName );
};
在工作中,我们广泛使用朋友测试代码 。 这意味着我们可以为主应用程序代码提供适当的封装和信息隐藏。 但是我们也可以使用单独的测试代码来检查内部状态和数据以进行测试。
只要说我不会使用friend关键字作为你设计的重要组成部分。
friend
关键字有很多好用处。 以下是我可以立即看到的两种用途:
朋友定义
朋友定义允许在类范围中定义一个函数,但函数不会被定义为成员函数,而是作为封闭名称空间的一个自由函数,并且除了依赖于参数的查找外,通常不会正常显示。 这对于操作符重载非常有用:
namespace utils {
class f {
private:
typedef int int_type;
int_type value;
public:
// let's assume it doesn't only need .value, but some
// internal stuff.
friend f operator+(f const& a, f const& b) {
// name resolution finds names in class-scope.
// int_type is visible here.
return f(a.value + b.value);
}
int getValue() const { return value; }
};
}
int main() {
utils::f a, b;
std::cout << (a + b).getValue(); // valid
}
私有CRTP基础类
有时候,你发现需要一个策略需要访问派生类:
// possible policy used for flexible-class.
template<typename Derived>
struct Policy {
void doSomething() {
// casting this to Derived* requires us to see that we are a
// base-class of Derived.
some_type const& t = static_cast<Derived*>(this)->getSomething();
}
};
// note, derived privately
template<template<typename> class SomePolicy>
struct FlexibleClass : private SomePolicy<FlexibleClass> {
// we derive privately, so the base-class wouldn't notice that,
// (even though it's the base itself!), so we need a friend declaration
// to make the base a friend of us.
friend class SomePolicy<FlexibleClass>;
void doStuff() {
// calls doSomething of the policy
this->doSomething();
}
// will return useful information
some_type getSomething();
};
你会在这个答案中找到一个非人为的例子。 使用它的另一个代码就是在这个答案中。 CRTP基础强制转换此指针,以便能够使用数据成员指针访问派生类的数据字段。
链接地址: http://www.djcxy.com/p/72929.html