我尝试按照以下定义访问朋友的方法。我有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教程。我错过了什么?
答案 0 :(得分:4)
您对friend
功能的理解是错误。如果向另一个类声明函数friend
,则意味着friend
函数可以访问该类的私有成员,这并不意味着friend
函数变为班级成员。
此处doStaff()
为friend
至B
,而非B
的成员。但是你在B
的对象上使用它,因此编译器说它不是该类的成员。使用friend
授予doStaff
访问权限B
private
成员的权限。
您正在关注的教程清楚地说明了这一点。 duplicate()
方法是Rectangle
的朋友,因此可以访问private
成员width
和height
,但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类的成员函数(它的家庭,你不需要让它成为朋友),它声明了一个名为doStuff的全局函数。你可以写
friend void A::doStuff(int i);
表示"如果有一个名为A的类,并且它有一个名为doStuff的成员带有一个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类中的私有成员。
正如您所看到的,宣布朋友类和朋友功能之间存在差异。