如何正确访问好友功能?

时间:2014-06-06 17:04:40

标签: c++ class methods member friend

我尝试按照以下定义访问朋友的方法。我有4个文件。两个标题:

标题a.h

#include "b.h"

class A
{
public:
    A();
    ~A();
    void testStuff(int i);
};

标题b.h

#include "a.h"

class A;

class B
{
    friend class A;

public:
    B();
    ~B();
    friend void doStuff(int i);
};

两个包含一些代码,a.cpp

#include "a.h"

void A::testStuff()
{
    B b {B()};
    b->doStuff(1);
}

b.cpp

#include "b.h"

void B::doStuff(int i)
{
    m_stuff = i;
}

如果我删除关键字friend,一切正常。但如果我将doStuff()声明为朋友,我会收到以下错误:

error: ‘class B’ has no member named ‘doStuff’

我尝试了this教程。我错过了什么?

3 个答案:

答案 0 :(得分:4)

您对friend功能的理解是错误。如果向另一个类声明函数friend,则意味着friend函数可以访问该类的私有成员,这并不意味着friend函数变为班级成员

此处doStaff()friendB,而非B的成员。但是你在B的对象上使用它,因此编译器说它不是该类的成员。使用friend授予doStaff访问权限B private成员的权限。

您正在关注的教程清楚地说明了这一点。 duplicate()方法是Rectangle的朋友,因此可以访问private成员widthheight,但duplicate()不会用作Rectangle的类方法。

总之,你的问题是错误的。您可以像任何免费(非类方法)功能一样访问friend函数。问题是friend函数如何访问它所关注的类的成员,并且如上所述,它可以访问该类中的所有内容,这是拥有友元函数的动机,即提供私人类的成员到局外人。

类似地,friend类可以访问它所熟悉的类的所有内容。

因此,对于您的问题,您要从friend移除doStaff,使其成为B的成员。但我想您的意图是使用friend方法,在这种情况下,您可以执行以下操作:

void doStuff(B b, int i)
{
  b.m_stuff = i; // it is friend function of B, so can access m_staff
}

或者您可以doStaff()成为A成员,然后您可以写

class A{
  //other members
  void doStaff(B& b, int i){ b.m_staff=i;}

void A::testStuff() {

  B b {B()};
  doStuff(b,1); //although u can just write "b.m_staff = 1;" right here
}

答案 1 :(得分:3)

没有必要在你自己的班级中声明方法作为"朋友"。因此,朋友声明如

friend void doStuff(int i);
在B级内部实际上并没有声明B类的成员函数(它的家庭,你不需要让它成为朋友),它声明了一个名为doS​​tuff的全局函数。你可以写

friend void A::doStuff(int i);

表示"如果有一个名为A的类,并且它有一个名为doS​​tuff的成员带有一个int参数,那么该成员函数就是朋友"。你写的是"如果某个地方有一个全局函数doStuff(int i),那么该函数就是朋友"。

所以你没有在你的类中声明B:doStuff(int i),并且非常合理地实现该函数会产生错误。

如果你想让A :: testStuff()被允许调用doStuff,你应该在B类中添加:

friend void A::testStuff ();

答案 2 :(得分:1)

当你做了" void B :: doStuff(int i)"时,你将doStuff()声明为B类的成员,但是 朋友关键字适用于非会员功能。它基本上是为了使一个不是类成员的函数可以访问该类的私有成员。

BTW,B将A类声明为朋友,这意味着您在A中声明的函数可以访问B类中的私有成员。

正如您所看到的,宣布朋友类和朋友功能之间存在差异。