根据C ++ Primer一书,作者提到我们可以将类成员函数指定为另一个类的朋友,而不是整个类(第634页)。
然后,我测试了这段代码:
class A
{
public:
friend void B::fB(A& a);
void fA(){}
};
class B
{
public:
void fB(A& a){};
void fB2(A& a){};
};
我只是希望fB()成为A类的朋友,而不是整个B类。但是代码产生了一个错误:'B' : is not a class or namespace name
。
(我使用的是Visual C ++ 2005)
答案 0 :(得分:16)
尝试将B定义放在A之前:
class A; // forward declaration of A needed by B
class B
{
public:
// if these require full definition of A, then put body in implementation file
void fB(A& a); // Note: no body, unlike original.
void fB2(A& a); // no body.
};
class A
{
public:
friend void B::fB(A& a);
void fA(){}
};
A
需要B
的完整定义。但是,B
需要了解A
,但不需要完整定义,因此您需要A
的前向声明。
答案 1 :(得分:3)
为了实现这一目标,需要在B
的定义之前了解A
的完整定义。
所以转发声明A
,因为B
不需要完整类型,并切换定义:
class A;
class B
{
public:
void fB(A& a){};
void fB2(A& a){};
};
class A
{
public:
friend void B::fB(A& a);
void fA(){}
};
答案 2 :(得分:3)
当编译器开始编译代码时(通常是从顶部开始),它会遇到这一行:
friend void B::fB(A& a);
通过B类的前向声明,编译器事先知道B的类型是否为Class与所有成员的实际声明。
在B类前向声明后运行以下代码。
///////////////
class B;
class A
{
public:
friend void B::fB(A& a);
void fA(){};
};
class B
{
public:
void fB(A& a){};
void fB2(A& a){};
};
仍然错误!!!
因为前向声明只是一个标识符的声明,程序员还没有给出完整的定义。所以编译器需要在A类之前完全定义B.
注意:A类定义依赖于B的类型和B的定义(即B :: fB),因此单独的前向声明无法解决,B类的完整定义需要在A类之前定义。
4运行此代码
////////
class B
{
public:
void fB(A& a){};
void fB2(A& a){};
};
class A
{
public:
friend void B::fB(A& a);
void fA(){}
};
仍然错误!!!
因为B类成员的职能是fB& fB2具有类型A的参数但是编译器不知道A的类型信息所以通过类A的前向声明,我们可以让编译器知道A的类型信息。 注意:B类定义仅取决于A的类型而不是A的成员,因此A的前向声明解决了步骤4。
////////////////////////
class A; // forward declaration of A needed by B
class B
{
public:
void fB(A& a);
};
class A
{
int i;
public:
friend void fA(A& a); //specifying function fA as a friend of A, fA is not member function of A
friend void B::fB(A& a); //specifying B class member function fB as a friend of A
};
// fA is Friend function of A
void fA(A& a)
{
a.i = 11; // accessing and modifying Class A private member i
cout<<a.i<<endl;
}
// B::fB should be defined after class A definition only because this member function can access Class A members
void B::fB(A& a)
{
a.i = 22; // accessing and modifying Class A private member i in Class B member function fB
cout<<a.i<<endl;
}
int main()
{
A a;
fA(a); // calling friend function of class A
B b;
b.fB(a); // calling B class member function fB, B:fB is friend of class A
return 0;
}
6练习:
// Cyclic dependency
#include<iostream>
using namespace std;
class A;
class B
{
public:
void fB(A& a);
friend void A::fA(B& b); //specifying class A's member function fA as a friend of B
};
class A
{
int i;
public:
void fA(B& b);
friend void B::fB(A& a); //specifying class B's member function fB as a friend of A
};
int main()
{
return 0;
}
答案 3 :(得分:2)
当编译器开始读取代码时(通常是从顶部开始),它遇到了这一行:
friend void B::fB(A& a);
然后编译器不理解这个B::
是什么意思。即使您稍后在代码中定义了此类,但编译器也不知道。因此,如果定义稍后在代码中存在,那么练习前进类(class Name;
)的声明通常是一件好事。
答案 4 :(得分:0)
首先向前声明A类,使其在B类定义中可见。然后定义包含B类朋友函数的A类。
答案 5 :(得分:0)
首先,在使用特定的类名之前,您必须先声明它。因此,在最初宣布B类之前,您需要在A类中使用B类的前向声明。
其次,在定义了两个类之后,您需要定义函数(使用两个类中的变量 - 这里是友元函数)。否则我们可能会遇到错误。
例如
#include<iostream>
using namespace std;
class alpha1;
class alpha2
{
public:
void put_bata(int a,int b);
};
void alpha2 :: put_bata(int a,int b)
{
alpha1 net;
net.roll=a;
net.id=b;
net.get_data();
}
class alpha1
{
int roll;
int id;
public:
void get_data(void)
{
cout<<roll<<endl<<id<<endl;
}
friend void alpha2 :: put_bata(int a,int b);
};
int main()
{
alpha2 gamma;
gamma.put_bata(5,6);
return 0;
}
在put_bata尝试访问roll和id之前会向我们显示错误,即使我们有一个类的前向声明,但下面给出的代码也能正常工作。
#include<iostream>
using namespace std;
class alpha1;
class alpha2
{
public:
void put_bata(int a,int b);
};
class alpha1
{
int roll;
int id;
public:
void get_data(void)
{
cout<<roll<<endl<<id<<endl;
}
friend void alpha2 :: put_bata(int a,int b);
};
void alpha2 :: put_bata(int a,int b)
{
alpha1 net;
net.roll=a;
net.id=b;
net.get_data();
}
int main()
{
alpha2 gamma;
gamma.put_bata(5,6);
return 0;
}
答案 6 :(得分:0)
@juanchopanza @ipkiss 关于您无法访问fB(A&amp; a)内部A的数据成员的问题,因为A尚未定义。您可以在定义A类之后定义函数fB(A&amp; a),而不是在单独的文件中定义它并包含它,以便fB(A&amp; a)能够看到A的数据成员。