第7周-任务2-使用成员函数、友元函数和一般函数

【预备工作:给出一个示例】

//例:使用成员函数、友元函数和一般函数的区别
#include <iostream>
using namespace std;
class Time
{public:
    Time(int h,int m,ints):hour(h),minute(m),sec(s){}
    void display1(); //成员函数声明
    friend voiddisplay2(Time &);  //友元函数声明
    int getHour(){returnhour;}
    intgetMinute(){return minute;}
    int getSec(){returnsec;}
 private:
    int hour;
    int minute;
    int sec;
};
void display3(Time &); //一般函数声明
 
void Time::display1() //成员函数的实现,dispaly1前加Time::
{   //以hour形式直接访问私有数据成员,实质是this->hour形式
    cout<<hour<<":"<<minute<<":"<<sec<<endl;
}
void display2(Time &t) //友元函数的实现,dispaly2前不加Time::,并不是类的成员函数
{   //不是类的成员函数,却可以t.hour的形式直接访问私有数据成员——友元
    cout<<t.hour<<":"<<t.minute<<":"<<t.sec<<endl;
}
void display3(Time &t) //一般函数的实现,dispaly1前加Time::
{   //只能用公共接口t.getHour()形式访问私有数据成员
    cout<<t.getHour()<<":"<<t.getMinute()<<":"<<t.getSec()<<endl;
}
int main()
{   Time t1(10,13,56);
    t1.display1();  //成员函数这样调用
    display2(t1);   //友员函数调用和一般函数无异
    display3(t1);   //一般函数的调用
    system("pause");
    return 0;
}

【要完成的任务】阅读上面的程序,仔细阅读注释。然后模仿完成求点类中距离的任务。

  你需要完成的任务是,利用成员函数、友元函数和一般函数,实现三个版本的求两点间距离的函数,并设计main()函数完成测试。此任务和上例的区别在于“距离是一个点和另外一个点的距离”,参数个数上有体现。下面是点类的部分代码。

class CPoint 
{
private: 
    double x;  // 横坐标 
    double y;  // 纵坐标 
 public:
    CPoint(doublexx=0,double yy=0):x(xx),y(yy){} 
    ……//请继续写需要的代码
};


【讲解视频】

第7周-任务2-使用成员函数、友元函数和一般函数

【参考解答】

#include<iostream>
#include<Cmath>
using namespace std;
class CPoint  
{
private:  
    double x;  // 横坐标 
    double y;  // 纵坐标 
 public: 
    CPoint(double xx=0,double yy=0):x(xx),y(yy){}  
	double distance1(CPoint &); //参数用const CPoint &更佳
	friend double distance2(CPoint &, CPoint &) ;
	double getX(){return x;}
	double getY(){return y;}
};

double distance3(CPoint &,CPoint &) ;

double CPoint::distance1(CPoint &p) 
{
	double dx=(x-p.x), dy=y-p.y; 
	return sqrt(dx*dx+dy*dy);
}

double distance2(CPoint &p1,CPoint &p2) 
{
	double dx=(p1.x-p2.x), dy=p1.y-p2.y; 
	return sqrt(dx*dx+dy*dy);
}

double distance3(CPoint &p1,CPoint &p2) 
{
	double dx=(p1.getX()-p2.getX()), dy=p1.getY()-p2.getY(); 
	return sqrt(dx*dx+dy*dy);
}

int main()
{	CPoint p1(10,13), p2(-5,6);
	cout<<"1. "<<p1.distance1(p2)<<endl;
	cout<<"2. "<<distance2(p1,p2)<<endl;
	cout<<"3. "<<distance3(p1,p2)<<endl;
	system("pause");
	return 0;
}


【批判一种不好的设计】

  许是受了示例的影响,一些同学设计了如下的程序:

#include<iostream>
#include<Cmath>
using namespace std;
class CPoint  
{
private:  
    double x;  // 横坐标 
    double y;  // 纵坐标 
 public: 
    CPoint(double xx=0,double yy=0):x(xx),y(yy){}  
	void distance1(CPoint &); 
	friend void distance2(CPoint &, CPoint &) ;
	double getX(){return x;}
	double getY(){return y;}
};

void distance3(CPoint &,CPoint &) ;

void CPoint::distance1(CPoint &p) 
{
	double dx=(x-p.x), dy=y-p.y; 
	cout<<sqrt(dx*dx+dy*dy)<<endl;//计算距离并直接输出
}

void distance2(CPoint &p1,CPoint &p2) 
{
	double dx=(p1.x-p2.x), dy=p1.y-p2.y; 
	cout<<sqrt(dx*dx+dy*dy)<<endl;  //计算距离并直接输出
}

void distance3(CPoint &p1,CPoint &p2) 
{
	double dx=(p1.getX()-p2.getX()), dy=p1.getY()-p2.getY(); 
	cout<<sqrt(dx*dx+dy*dy)<<endl;   //计算距离并直接输出
}

int main()
{	CPoint p1(10,13), p2(-5,6);
	cout<<"1. 使用成员函数";
	p1.distance1(p2);
	cout<<"2. 使用友元函数";
	distance2(p1,p2);
	cout<<"3. 使用一般函数";
	distance3(p1,p2);
	system("pause");
	return 0;
}

  是否完成了任务?不可否认。但是,在计算距离的函数中直接输出结果,函数返回值类型为void型的做法很不专业。distance函数的功能是求距离,“求”距离,也即得到一个距离值即可,我们需要围绕这一语义设计函数,其结果就应该是一个值,表示距离的值。所以,求出了距离,很自然地将距离作为返回值即可。至于这个值如何利用,是调用distance函数的人需要考虑的事情了。举一例说明,比如给出三点构成三角形,要求周长,求边长——两点间的距离是不可回避的事情,这时求得的距离就不是输出就行了,而是返回值再去参与其他运算。

  所以,在设计函数时一般有个原则:函数中尽可以不涉及输入和输出。必要的入口数据由参数给出,而计算结果通过返回值返回,当结果不止一个时,往往通过指针或引用给出。





上一篇:如何通过ECS连接到HybridDB for PostgreSQL?


下一篇:虚指针存在证明及虚函数表