[英]C++ friend classes and friend member functions
我正在学习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)?
这是一个朋友类的示例以及如何使用它。 这是在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的成员函数访问Square的私有成员和受保护成员。 更具体地说,Rectangle访问成员变量Square :: side,该变量描述正方形的侧面。
此示例中还有其他新内容:在程序的开头,有一个空的Square类声明。 这是必需的,因为类Rectangle使用Square(作为成员转换中的参数),而Square使用Rectangle(将其声明为朋友)。
除非指定,否则从不建立友谊:在我们的示例中,Square将Rectangle视为朋友类,但Rectangle不将Square视为朋友。 因此,Rectangle的成员函数可以访问Square的受保护成员和私有成员,但不能相反。 当然,如果需要,也可以将Square声明为Rectangle的朋友,以授予此类访问权限。
友谊的另一个特性是,它们不是可传递的:除非明确指定,否则朋友的朋友不会被视为朋友。
只是让class B
class A
class B
的朋友。 这样做没有不利影响。
如果您绝对肯定要行使更细粒度的控制,则可以使用这样的代理类来做到这一点(使用剥离了示例的示例):
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; }
};
现在,您可以在B::set
和B::get
(仅)中使用Proxy::get_i(a)
代替ai
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.