在类里,我们更倾向于更多使用private类型来实现封装性,但有的时候,我们必须访问类里的一些数据,也许还会做出修改,如果因为这样我们就把private改成了public参数类型,那么封装性就不太好了。
一个可取的(feasible)做法是数据限定为private,并且提供public成员函数对其进行操作,这样的成员函数我们就称为访问器和修改器,我们一般把访问器取名为getXX(),修改器取名为setXX(),有时候只需其中之一。
class Rectangle
{
public:
double area();
double perimeter(); //perimeter是周长的意思
//下面是宽度width的访问器和修改器
double getWidth() {return width;}
void setWidth(double newWid)
{
if(newWid>0)
width=newWid;
}
//height我们就不说了,一个意思
private:
double width;
double height;
}
虽然这么看起来很简单,不过这给封装的对象的打分又提高了一点点。
我们再看看友元:
某些情况下,有的函数需要访问一个类的私有数据,例如我们定义一个class来存一个复数,内有private的数据成员实部(real)与虚部(empty),public成员函数我们先不管。然后我们再定义一个全局函数
Complex add(const Complex& c1,const Complex& c2) //这里面是用的c++的引用,引用又叫做取别名
{
Complex temp;
temp.real=c1.real+c2.real;
temp.empty=c1.empty+c2.empty; //Error:全局函数不能访问类的私有成员
return temp;
}
为了解决这个问题,我们首先想到的是private改为public,但是我们的初心是保持封装性,so C++引入了关键字friend,如果你想让非成员函数访问一个类的私有数据,应该再类的内部把它声明为友元friend。
我们举一个例子,一个extract:
class Y
{
public:
void f(X*); //对这个函数的声明而言,只需要知道X是一个类型就行
};
class X
{
int i;
public:
void initialize();
friend void g(X*,int); //全局函数友元
friend void Y::f(X*); //成员函数友元
friend class Z; //友元类
};
//后面就是进一步解释每一个小部分的实现代码,我们举一个例子就行
void g(X* x ,int i)
{
x->i=i;//访问允许
}
值得一提的是,friend关系是不可以传递的,比如A是B的朋友,B是C的朋友,但是A和C他们不一定是朋友,说不定还是情敌。
当然,friend关系也是不可继承的:基类友元不会成为其派生类的友元。
friend的合理使用有利于控制复杂度,可是不合适的使用会增大耦合性,我们还是尽量少用友元,反正,毕竟只是一个了解的水文。