【发布时间】:2017-06-28 15:14:58
【问题描述】:
我正在学习 C++ 类中的友元函数、友元类和友元成员函数; 现在,以下代码可以正常编译:
#include <iostream>
class A
{
public:
friend class B;
//friend void B::set(int i);
//friend int B::get();
friend int function(A a);
A(int i);
void set(int i);
int get();
private:
int i;
};
A::A(int i) : i(i)
{
}
void A::set(int i)
{
this->i = i;
}
int A::get()
{
return i;
}
class B
{
public:
B(A a);
void set(int i);
int get();
private:
A a;
};
B::B(A a) : a(a)
{
}
void B::set(int i)
{
a.i = i;
}
int B::get()
{
return a.i;
}
int function(A a);
int main(int argc, char *argv[])
{
A a(0);
std::cout << "in A i=" << a.get() << std::endl;
a.set(10);
std::cout << "in A i=" << a.get() << std::endl;
B b(a);
std::cout << "in B i=" << b.get() << std::endl;
b.set(21);
std::cout << "in B i=" << b.get() << std::endl;
std::cout << "function returns " << function(a) << std::endl;
}
int function(A a)
{
return a.i;
}
我能够授予 B 类友谊并在 A 类中执行“函数”,而无需前向声明 B 类或函数“函数”。 现在,如果我想为 B 类中的两个成员函数授予友谊,如果我在定义 A 类之前不定义 B 类,则它不起作用:
#include <iostream>
class B; // doesn't work, incomplete type (complete type needed)
class A
{
public:
//friend class B;
friend void B::set(int i);
friend int B::get();
friend int function(A a);
A(int i);
void set(int i);
int get();
private:
int i;
};
A::A(int i) : i(i)
{
}
void A::set(int i)
{
this->i = i;
}
int A::get()
{
return i;
}
B::B(A a) : a(a)
{
}
void B::set(int i)
{
a.i = i;
}
int B::get()
{
return a.i;
}
int function(A a);
int main(int argc, char *argv[])
{
A a(0);
std::cout << "in A i=" << a.get() << std::endl;
a.set(10);
std::cout << "in A i=" << a.get() << std::endl;
B b(a);
std::cout << "in B i=" << b.get() << std::endl;
b.set(21);
std::cout << "in B i=" << b.get() << std::endl;
std::cout << "function returns " << function(a) << std::endl;
}
int function(A a)
{
return a.i;
}
但我无法在定义 A 类之前定义 B 类,所以我被卡住了。前向声明(不定义)B 类也不起作用。
所以我的问题是:
1) 为什么我不需要在友谊声明中转发声明一个函数或整个类,但如果我需要指定该类的成员函数,我确实需要定义一个类? 我知道友谊声明不是常识中的声明(它们只是授予访问权限,而不是转发声明任何内容)。
2) 我怎样才能使我的代码编译(除了将 B 中的 A 成员对象声明为 A *a)?
【问题讨论】:
-
其实不需要把B类的成员函数声明为友元函数,因为A类有公共接口。
-
@VladfromMoscow 这确实是一个人为的例子。我只是想了解它为什么不起作用以及如何解决这个问题。
-
“我不能在定义 A 类之前定义 B 类”为什么?
-
@Luca 不起作用,因为编译器不知道B类是否确实有这些成员函数。
-
@n.m.实际上它确实有意义