友元的作用举例来说--写一个神经网络,写完以后想写一个单元测试,和神经网络放在一个命名空间里。写的神经网络是一个类,里面有多个私有变量,而单元测试不可避免地要用到这些私有变量。如果这是在java里,我就只能再写上一堆访问器了;而在C++里,只用把这个单元测试函数声明成类的友元,就能随心所欲地访问私有变量,简直不要太痛快。
但同时也需要慎用friend关键字,它会破坏掉封装的隐藏性。
如果一个函数被定义为一个类的友元函数,那么这个函数可以访问所有私有和受保护的数据。
要使函数成为类的友元函数,可以在类内部以private或public部分的形式声明它,并在声明之前加上关键字friend,如下所示。
class Temperature
{
int celsius;
public:
Temperature():celsius(0);
friend int temp( Temperature ); //声明友元函数
};
这里,temp是类Temperature的友元函数。因此,它可以访问类的所有私有成员和受保护成员。
#include <iostream>
using namespace std;
class Temperature
{
int celsius;
public:
Temperature():celsius(0);
friend int temp( Temperature );
};
int temp( Temperature t ) // 友元函数定义
{
t.celsius = 40;
return t.celsius;
}
int main()
{
Temperature tm;
cout << "Temperature in celsius : " << temp( tm ) << endl;
return 0;
}
//OUTPUT:Temperature in celsius : 40
声明了一个函数“temp”作为类“Temperature”的友元函数。在friend函数中,我们直接访问了类'Temperature'的私有成员摄摄氏度。 主函数的第一个语句创建了类'Temperature'的对象'tm',从而调用其构造函数,并为其数据成员摄氏度赋值0。 主函数的第二个语句调用temp函数,它为摄氏温度赋值40。
两个类的同一个f可以有同一个友元函数。
#include <iostream>
using namespace std;
class B; //declaration of class B
class A
{
int value;
public:
A():value(5){}
friend int sum(A, B); // 声明友元函数
};
class B
{
int value;
public:
B():value(3);
friend int sum(A, B); // 声明友元函数
};
int sum( A v1, B v2 ) // 定义友元函数
{
return (v1.value + v2.value);
}
int main()
{
A a;
B b;
cout << "Sum : " << sum( a, b ) << endl;
return 0;
}
//OUTPUT:Sum : 8
在本例中,将sum()声明为a和b类的friend函数。因此,该函数现在可以访问这两个类的私有成员和受保护成员。这两个类的对象都作为函数的参数传递。
注意,我们在定义类A之前声明了类B,因为在类A的主体中,friend函数接受参数'A'和'B'。
在学校里能使一个班成为另一个班的朋友。在这种情况下,类中声明为friend的所有成员函数将成为另一个类的friend函数。
class A
{
friend class B;
};
class B
{
};
上面的代码中,B类被声明为a类的朋友。所以现在B类的所有成员函数都变成了A类的友元函数。
再来看一个例子
#include <iostream>
using namespace std;
class Square
{
friend class Rectangle; // 将Rectangle声明为友元类
int side;
public:
Square ( int s )
{
side = s;
}
};
class Rectangle
{
int length;
int breadth;
public:
int getArea()
{
return length * breadth;
}
void shape( Square a )
{
length = a.side;
breadth = a.side;
}
};
int main()
{
Square square(5);
Rectangle rectangle;
rectangle.shape(square);
cout << rectangle.getArea() << endl;
return 0;
}
//OUTPUT:25
将Rectangle声明为Square的friend类。因此,现在Rectangle的所有函数都可以直接访问Square的任何私有成员。 在主函数中,第一个语句创建了类square的对象'square',从而调用它的构造函数并将5分配给它的数据成员端。 主函数中的第二条语句创建了类rectangle的对象'rectangle'。 在第三个语句中,'rectangle'调用函数shape(),它的参数是类Square的对象。在'shape()'函数中,'side' (Squa的私有数据成员)的值
还可以使一个类的函数成为另一个类的友元函数。这样做的方法与作为类的友元创建函数的方法是一样的。惟一的区别是,需要在声明中把class_name::写在类中函数名的前面,该类的友元函数是被声明的。friend函数仅在类中指定,其整个主体在类外声明。从下面给出的例子可以清楚地看出。
class A; // A再B之前声明
class B
{
display( A a ); //只有指定的。没有具体实现
};
class A
{
friend void B::display( A );
};
void B::display(A a) //在B中实现
{
}
下面是一个实际的例子
using namespace std;
class A;
class B
{
public:
void display(A obj);
};
class A
{
int x;
public:
A()
{
x = 4;
}
friend void B::display(A);
};
void B::display(A obj)
{
cout << obj.x << endl;
}
int main()
{
A a;
B b;
b.display(a);
return 0;
}
//OUTPUT:4
//需要使用gcc filename.cpp -lstdc++ -o文件名来运行这段代码