我在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级友谊并发挥作用&#34;功能&#34;在A类中没有前瞻声明B类,或函数&#34;功能&#34;。 现在,如果我想给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)?
答案 0 :(得分:1)
以下是朋友类的示例以及如何使用它。这是cplusplus.com我发布这个的原因是因为你的例子并没有真正说明在c ++中正确使用友谊。我希望这能说明你应该如何/为什么要使用友谊,这可以导致你解决你的前瞻性声明问题。
// friend class
#include <iostream>
using namespace std;
class Square;
class Rectangle {
int width, height;
public:
int area ()
{return (width * height);}
void convert (Square a);
};
class Square {
friend class Rectangle;
private:
int side;
public:
Square (int a) : side(a) {}
};
void Rectangle::convert (Square a) {
width = a.side;
height = a.side;
}
int main () {
Rectangle rect;
Square sqr (4);
rect.convert(sqr);
cout << rect.area();
return 0;
}
在此示例中,类Rectangle是Square允许的类的朋友 Rectangle的成员函数用于访问私有成员和受保护成员 广场更具体地说,Rectangle访问成员变量 Square :: side,描述了正方形的一面。
在这个例子中还有一些新东西:在开头 程序中,有一个类Square的空声明。这是 必需因为类Rectangle使用Square(作为参数) 成员转换),而Square使用Rectangle(将其声明为朋友)。
除非另有说明,否则友谊永远不会对应:在我们的示例中, Rectangle被Square视为朋友类,而Square则不是 被Rectangle视为朋友。因此,成员的职能 Rectangle可以访问Square的受保护和私有成员但是 而不是相反。当然,Square也可以宣布 如果需要,Rectangle的朋友可以授予此类访问权限。
友谊的另一个特性是它们不是传递性的: 除非明确表示朋友的朋友不被视为朋友 指定。
答案 1 :(得分:0)
让class B
成为class A
的朋友。这样做没有任何不利影响。
如果你绝对肯定想要进行更细粒度的控制,你可以使用像这样的代理类(使用剥离到裸骨的例子)来实现它:
class Proxy;
class A
{
public:
friend class Proxy;
A(int i);
private:
int i;
};
class B
{
public:
B(A a);
void set(int i);
int get();
private:
A a;
};
class Proxy
{
friend void B::set(int);
friend int B::get();
static int& get_i(A& a) { return a.i; }
static const int& get_i(const A& a) { return a.i; }
};
您现在可以在Proxy::get_i(a)
和a.i
(仅限)B::set
中使用B::get
代替segments()
。