我一直在阅读c++常见问题,对朋友声明很好奇。我个人从未使用过它,但我对探索这门语言很感兴趣。

使用friend的一个好例子是什么?


读了一些常见问题,我喜欢<< >>操作符重载和添加作为这些类的朋友的想法。然而,我不确定这如何不会破坏封装。什么时候这些异常可以保持在OOP的严格范围内?


当前回答

在工作中,我们广泛地请朋友来测试代码。这意味着我们可以为主应用程序代码提供适当的封装和信息隐藏。但我们也可以有单独的测试代码,使用朋友来检查内部状态和数据进行测试。

可以说,我不会将friend关键字作为设计的重要组成部分。

其他回答

我使用friend的一个特定实例是在创建Singleton类时。friend关键字允许我创建一个访问器函数,这比总是在类上使用“GetInstance()”方法更简洁。

/////////////////////////
// Header file
class MySingleton
{
private:
    // Private c-tor for Singleton pattern
    MySingleton() {}

    friend MySingleton& GetMySingleton();
}

// Accessor function - less verbose than having a "GetInstance()"
//   static function on the class
MySingleton& GetMySingleton();


/////////////////////////
// Implementation file
MySingleton& GetMySingleton()
{
    static MySingleton theInstance;
    return theInstance;
}

在做TDD的时候,我经常使用c++中的'friend'关键字。

朋友能知道我的一切吗?


更新:我从Bjarne Stroustrup网站上找到了这个关于“朋友”关键字的有价值的答案。

“好友”是一种授予访问权限的显式机制,就像会员资格一样。

好友对于回调也很有用。可以将回调函数作为静态方法来实现

class MyFoo
{
private:
    static void callback(void * data, void * clientData);
    void localCallback();
    ...
};

回调在内部调用localCallback, clientData中有你的实例。在我看来,

还是……

class MyFoo
{
    friend void callback(void * data, void * callData);
    void localCallback();
}

这允许友元在cpp中被定义为c风格的函数,而不会使类变得混乱。

类似地,我经常看到的一种模式是将一个类的所有真正的私有成员放到另一个类中,该类在头文件中声明,在cpp中定义,并加为好友。这允许编码器向头文件的用户隐藏类的很多复杂性和内部工作。

在头文件中:

class MyFooPrivate;
class MyFoo
{
    friend class MyFooPrivate;
public:
    MyFoo();
    // Public stuff
private:
    MyFooPrivate _private;
    // Other private members as needed
};

在cpp中,

class MyFooPrivate
{
public:
   MyFoo *owner;
   // Your complexity here
};

MyFoo::MyFoo()
{
    this->_private->owner = this;
}

这样就更容易隐藏下游不需要看到的东西。

在工作中,我们广泛地请朋友来测试代码。这意味着我们可以为主应用程序代码提供适当的封装和信息隐藏。但我们也可以有单独的测试代码,使用朋友来检查内部状态和数据进行测试。

可以说,我不会将friend关键字作为设计的重要组成部分。

另一种用法:friend(+虚拟继承)可以用来避免从一个类派生(又名:“make a class underivable”)=> 1,2

从2:

 class Fred;

 class FredBase {
 private:
   friend class Fred;
   FredBase() { }
 };

 class Fred : private virtual FredBase {
 public:
   ...
 };