友元&运算符重载

---------------友元的成员函数------------------------------

#include <iostream>
#include <cmath>
using namespace std;
class Point;                        //声明Point类
class line                            //定义line类
{
    public:
        float dis(Point& p1,Point& p2); // 友元函数的原型,作为line类的成员函数
};
class Point                            //定义Point类
{
    private:
        int x,y;                        //private型数据成员x和y
        friend float line::dis(Point &p1,Point &p2);//友元的声明 (类line的成员函数是类Point的友元函数)
    public:
        Point(int i=0,int j=0)            //Point类的构造函数,带缺省参数
        {
            x=i;
            y=j;
        }
        void disp()                        //成员函数disp(),用来输出点的信息
        {
            cout<<"("<<x<<","<<y<<")";
        }
};
int main()
{
    line line1;                                //声明一个line类的对象line1
    Point p1(1,2),p2(4,5);                    //声明两个Point类的对象p1和p2
    p1.disp();                                //输出点p1的信息 
    cout<<""; 
    p2.disp();                                //输出点p2的信息
    cout<<"距离="<<line1.dis(p1,p2)<<endl;    //通过调用line1的成员函数dis计算两个点间的距离
    return 0;
}
float line::dis(Point& p1,Point& p2)        //line类内成员函数dis的实现,作为Point类的友元函数
{
    float d;
    d=sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));//可访问Point类对象的private成员
    return d;
} 

注:

  (1) 友元函数所在的类必须先定义,即 line 类必须定义在 point 类之前,对类实现位置没有具体要求。

  (2) 根据 "对象的生存期、作用域和可见域" 可知,在 line 类的 dis 函数中需要传递对象参数,因此,

必须在 line 类前对 point 进行声明,且由于 point 类的定义在 line 类的定义后面,编译器无法决定 dis 函

数中point 对象的大小和成员组成,因此,只能对 point 对象采用传引用或传指针处理,而且,dis函数不

能定义为内联格式,必须定义在 point 类定义之后。

-----------------------友元类-------------------------------------

#include <iostream>
#include <cmath>
using namespace std;
class cz;                //声明类cz
class Point                //定义Point类
{
    private:
        int x,y;
        friend class cz;            //友元类的声明,位置同样不受限制
    public:
        Point(int i=0,int j=0)    //构造函数,带缺省参数值
        {
            x=i;
            y=j;
        }
        void disp()            //成员函数,输出点的信息
        {
            cout<<"("<<x<<","<<y<<")";
        }
}; 
class cz                //类cz的定义,其中所有的函数都是Point类的友元函数
{
    public:
        float dis(Point& p1,Point& p2)        //可访问p1和p2的private成员
        {
            float d;
            d=sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
            return d;
        } 
        void Set(Point* p1,int a,int b)        //可访问p1和p2的private成员
        {
            p1->x=a;
            p1->y=b;
        }
};
int main()
{
    cz cz1;                    //声明一个cz类的对象cz1
    Point p1(1,2),p2(4,5);    //声明两个Point类对象p1和p2
    p1.disp();                //输出点p1的信息 
    cout<<"";
    p2.disp();                //输出点p2的信息
    cout<<"距离="<<cz1.dis(p1,p2)<<endl;//调用cz1的成员函数dis计算两点间距
    cz1.Set(&p1,3,4);        //调用cz1的成员函数Set改写p1中的private成员x和y
    p1.disp();                //修改后的点p1信息输出
    cout<<endl;                //涣行
    return 0;
}

  解析:类 cz 被声明为类 point 的友元类,则 cz 中的所用成员函数都成为 point 的友元函数,当把

cz 类声明为 point 类的友元类时,并不要求先定义 cz ,只要先对其进行声明即可,关于友元类有以下

需要注意:

(1)友元关系是单向的,不具有交换性。若类 X 是类Y的有缘,类Y不一定是类X的友元,要看在类中是

否有相应的声明。

(2)友元关系不具有传递性。若类X是类Y的友元,类Y是类Z的友元,类X不一定是类Z的友元,同样要

看在类中是否有相应的声明。

(3)友元关系不能被继承。

 -------------------运算符重载----------------------------------------------------

类complex
private
: double real,imag; //private成员,分别代表实部和虚部 public: complex(double r=0.0,double i=0.0) //构造函数,带缺省参数值 { real=r; imag=i; }

成员函数形式:

complex& complex::operator ++() 

//前置++的实现 { cout<<"前置++"<<endl; real+=1; imag+=1; return (*this); }
complex complex::operator ++(int)

//后置++的实现,体会和前置++的区别 { cout<<"后置++"<<endl; complex ctemp=*this; ++(*this); return ctemp; }

 

 

 

 

 

 

友元函数形式:

complex& operator ++(complex& C1)
//前置++的实现 { cout<<"前置++"<<endl; C1.real+=1; C1.imag+=1; return C1; }
complex operator ++(complex& C1,int)
//后置++的实现,体会和前置++的区别 { cout<<"后置++"<<endl; complex ctemp=C1; ++C1; return ctemp; }

 

 

 

 

 

 ----------------------------------赋值运算符重载-------------------------------

complex& complex::operator =(const complex& CC) //成员函数赋值运算符重载的实现
{
    if (this==&cp)               //首先判断是否为自赋值,若是则返回当前对象
        return (*this);
    price =cp.price;             //如果不是自赋值,先对price赋值
    delete[] brand;              //防止内存泄露,先释放brand指向的内容
    brand=NULL;
    brand=new char[strlen(cp.brand)+1];  //为brand重新开辟一块内存空间
    if (brand!=NULL)             //如果开辟成功
    {
        strcpy(brand,cp.brand);  //复制字符串
    }
    return (*this);              //返回当前对象的引用,为的是实现链式赋值
}

 

 

 

 

 

posted @ 2013-05-14 09:38  sky&moon  阅读(310)  评论(0编辑  收藏  举报