网站地图
首页
新闻
电影新闻
电视新闻
人物新闻
专题策划
影评
最新影评
新片热评
经典赏析
媒体评论
电影院
北京影讯
上海影讯
广州影讯
深圳影讯
成都影讯
电影库
典藏佳片
全球新片
即将上映
票房榜
社区
日志
相册
电影
好友
专辑
收藏
影视杂谈
明星时尚
文化休闲
群组
话题
达人
排行榜
电影榜
电视榜
人物榜
日志榜
话题榜

Lee.1979

TIME Goes Easy Here .

http://i.mtime.com/1538728/

您当前的位置: 社区>> 博客>>

编辑 | 删除 友元

Lee_1979 发布于:

友元是为了解决运行效率和封装性而设立的概念。
设想一个问题:输入两个(x,y)坐标,输出两点间距离。(用面向对象方法编写程序)
首先建立类Point。
class Point{
private:
     double x,y;
public:
    Point(double xx,double yy){x=xx;y=yy;}  //构造函数
...
}
然后,我们要计算两点间的距离。
把这个函数叫Distance(,),参数是Point类的两个对象;Distance()要计算距离,就必须访问对象里的私有变量x,y。如下:
Distance(Point &a, Point &b){
  double dx = a.x - b.x;
  double dy = a.y - b.y;
  return sqrt(dx*dx+dy*dy);
}
这个函数可能是三种情况之一:独立于类Point的全局函数,类Point的成员函数,类Point的友元函数。1)非类Point成员函数首先被排除,因为Distance(,)需要访问类Point对象的Private变量,这是不允许的。2)类Point的成员函数,理论上被允许,但调用Distace(,)则必须通过对象,增加了程序的复杂度,许多成员需要被反复调用。
3)友元函数应运而生,加上friend,它可以访问类内的private变量,而调用时不必增加而外开销。
完整程序:
#include <iostream>
#include <math.h>
using namespace std;

class Point{
private:
double x,y;
public:
Point(double xx,double yy){x=xx;y=yy;}  //构造函数
void Getxy();                           //获取输入的(x,y)坐标并显示
friend double Distance( Point &a,Point &b );//友元函数Distance(,)用于计算两点间距离
};
void Point::Getxy(){
cout<<"("<<x<<","<<y<<")"<<endl;
}
double Distance( Point &a,Point &b ){
double dx = a.x - b.x ;
double dy = a.y - b.y ;
return sqrt( dx*dx + dy*dy );
}

int main(){
cout<<"输入两点坐标:";
double a,b,c,d;
cin>>a>>b>>c>>d;
Point p1(a,b);
Point p2(c,d);
p1.Getxy();
p2.Getxy();
double re = Distance(p1,p2);
cout<<"两点间距离是:"<<re<<endl;
return 0;
}

当然,另外的方法是友元类;把Distance(,)放在这个友元类里。这个问题友元函数就可以解决了,较大的系统里可以使用友元类,涉及设计模式时比较常用的方法。

------------------------------------------------------------------------------

友元类举一个栈的例子。

首先,栈节点使用结构体。

#include <iostream>
using namespace std;

struct Node{                 //节点结构体
 int data;                //数据(int型)
 Node *prev;              //指针
};

class Stack{                 //栈类
private:
 Node *top;               //栈指针
public:
 Stack(){top = NULL;};    //构造函数,初始化栈为空
 void Push(int i);        //压入栈
 int Pop();               //弹出栈

};

void Stack::Push(int i){
 Node *p = new Node;  //指针在定义时必须分配空间
   p->data = i;
  p->prev = top;
 top = p;
}
int Stack::Pop(){
 if(top){                     //判断是否到栈底(必须,否则会导致内存数据丢失)
  int c = top->data;
  Node *t = top ;          //为了delete弹出后的空白指针空间
  top = top->prev;         //设置新的栈顶元素
  delete t;
  return c; 
 }
 return 0;
}

int main(){
 Stack s;
 s.Push(4);
 s.Push(7);
 s.Push(8);
 s.Push(9);
 s.Push(1);
 for(int i=1;i<5;i++)
  cout<<s.Pop();
 cout<<endl;

 return 0;
}

 

其次,栈节点使用类。这需要使用友元类。

class Node{
private:
 int data;
 Node *prev;
public:
 Node(int d,Node* p){data = d; prev = p;}
 friend class Stack;
};

其余的代码只需要更改:

void Stack::Push(int i){
 Node *p = new Node(i,top);
 top = p;
}

这是因为strct和class的初始化不一样。

两个类之间是强的组合关系,Stack可以使用Node的私有数据。(友元类一般都是组合关系)

输出结果就是:19874

 

回复 (0) | 收藏 (0) | 127 次阅读 |
标签:

Lee_1979 (西安)

男