为什么有些运算符重载不能重载为友元函数

为什么有些运算符重载不能重载为友元函数,第1张

因为类的成员二元运算符重载要求运算符左 *** 作数为运算符函数的第一个参数,而流类库中的>>则要求第一个参数为ostream的引用,所以不能作为类成员,只能作为友元

可能比较难理解,应用时知道把它重载为友元就可以了

哎,,,叫你求助我又不求助,无语

其实我早写好了

我的重载为-,如果你改+,就把之前的重载删除,就可以了

#include<iostream>

#define MAX 10

using namespace std;

class matrix;

matrix& operator-(matrix& b,const matrix& c);

class matrix

{

private:

    int row,col,(a)[MAX];

public:

    matrix(){}

    matrix(int r,int c,int (b)[MAX]):row(r),col(c),a(b){}

    matrix& operator+(const matrix& b)

    {

        for(int i=0;i<row;i++)

            for(int j=0;j<col;j++)

                a[i][j]=a[i][j]+ba[i][j];

        return this;

    }

    friend matrix& operator-(matrix& b,const matrix& c)

    {

           for(int i=0;i<brow;i++)

            for(int j=0;j<bcol;j++)

             ba[i][j]=ba[i][j]-ca[i][j];

        return b;

    }

    void show()

    { 

          for(int i=0;i<row;i++)

        {

            for(int j=0;j<col;j++)

                cout<<a[i][j]<<" ";

            cout<<endl;

        }

    }

};

void main()

{

    int row =2 ,col =3,a[2][MAX]={{1,2,3},{4,5,6}};

    matrix mat1(row,col,a);

    int b[2][MAX]={{4,3,2},{1,2,3}};

    matrix mat2(row,col,b);

    matrix mat3;

    mat3 = mat1 + mat2;

    cout<<"mat3"<<endl;

    mat3show();

    cout<<"mat1"<<endl;

    mat1show();

    cout<<"mat4"<<endl;

    matrix mat4;

    mat4 = mat1 - mat2;

    mat4show();

}

运算符重载为类的友元函数,要分双目运算符和单目运算符两种情况,函数的参数个数不一样,重载的具体形式可以参见 <a href="http://wenwensosocom/z/urlalertpageesp=shttp%3a%2f%2fwwwjizhuomicom%2fsoftware%2f117html" target="_blank">http://wwwjizhuomicom/software/117html</a>上的讲解。

因为 *** 作符左侧的变量是调用的对象 如a+b 相当于aopreater+(b),

所以可以看 *** 作符的左侧是什么样的对象。

如a+b,左侧的a是一个自己定义的类的对象,所以是成员函数,

cout<<a, <<的左边是cout 是一个ostream对象,非你自己定义的对象,所以是友元

1友元函数的简单介绍

11为什么要使用友元函数

在实现类之间数据共享时,减少系统开销,提高效率如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数具体来说:为了

使其他类的成员函数直接访问该类的私有变量即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数

实际上具体大概有下面两种情况需要使用友元函数:(1)运算符重载的某些场合需要使用友元(2)两个类要共享数据的时候

12使用友元函数的优缺点

121优点:能够提高效率,表达简单、清晰

122缺点:友元函数破环了封装机制,尽量不使用成员函数,除非不得已的情况下才使用友元函数

2友元函数的使用

21友元函数的参数:

因为友元函数没有this指针,则参数要有三种情况:

211 要访问非static成员时,需要对象做参数;

212 要访问static成员或全局变量时,则不需要对象做参数;

213 如果做参数的对象是全局对象,则不需要对象做参数;

22友元函数的位置

因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且没有区别

23友元函数的调用

可以直接调用友元函数,不需要通过对象或指针

24友元函数的分类:

根据这个函数的来源不同,可以分为三种方法:

241普通函数友元函数

2411 目的:使普通函数能够访问类的友元

2412 语法:

声明:friend + 普通函数声明

实现位置:可以在类外或类中

实现代码:与普通函数相同

调用:类似普通函数,直接调用

所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。

运算符也可以重载

运算符重载是对已有的运算符赋予多重含义

必要性

C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)

(一) C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。

(二) C++允许重载的运算符C++中绝大部分的运算符允许重载

不能重载的运算符只有5个:

(1) 成员访问运算符

(2) 作用域运算符∷

(3) 条件运算符:

(4) 成员指针运算符

(5) 编译预处理命令的开始符号#

(三) 重载不能改变运算符运算对象(即 *** 作数)的个数。

(四) 重载不能改变运算符的优先级别。

(五) 重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。

(六) 重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。

(七) 用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。

① 赋值运算符(=)可以用于每一个类对象,可以利用它在同类对象之间相互赋值。

② 地址运算符&也不必重载,它能返回类对象在内存中的起始地址。

总之,当C++语言原有的一个运算符被重载之后,它原先所具有的语义并没有消失,只相当于针对一个特定的类定义了一个新的运算符。

运算符重载可以使用成员函数和友元函数两种形式。可以参考以下的经验:

(1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。

(2)单目运算符最好重载为成员函数。

(3) 对于复合的赋值运算符如+=、-=、=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。

(4) 对于其它运算符,建议重载为友元函数。

运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:

函数类型 operator 运算符名称 (形参表列)

{

对运算符的重载处理

}

重载为类成员函数时参数个数=原 *** 作数个数-1

(后置++、--除外)

重载为友元函数时 参数个数=原 *** 作数个数,且至少应该有一个自定义类型的形参。

将“+”、“-”运算重载为复数类的成员函数。

规则:

实部和虚部分别相加减。

*** 作数:

两个 *** 作数都是复数类的对象。

#include<iostream>

using namespace std;

class complex //复数类声明

{

public: //外部接口

complex(double r=00,double i=00)

{

real=r;

imag=i;

} //构造函数

complex operator + (complex c2); //+重载为成员函数

complex operator - (complex c2); //-重载为成员函数

void display(); //输出显示复数

private: //私有数据成员

double real; //复数实部

double imag; //复数虚部

};

complex complex::operator +(complex c2) //重载函数实现

{

complex c;

creal=real+c2real;

cimag=imag+c2imag;

return complex(creal,cimag);

}

complex complex::operator -(complex c2) //重载函数实现

{

complex c;

creal=real-c2real;

cimag=imag-c2imag;

return complex(creal,cimag);

}

void complex::display()

{ cout<<"("<<real<<","<<imag<<“i”<<")"<<endl; }

void main() //主函数

{ complex c1(5,4),c2(2,10),c3; //声明复数类的对象

cout<<"c1="; c1display();

cout<<"c2="; c2display();

c3=c1-c2; //使用重载运算符完成复数减法

cout<<"c3=c1-c2=";

c3display();

c3=c1+c2; //使用重载运算符完成复数加法

cout<<"c3=c1+c2=";

c3display();

}

程序输出的结果为:

c1=(5,4i)

c2=(2,10i)

c3=c1-c2=(3,-6i)

c3=c1+c2=(7,14i)

在本程序中对运算符“+”,”-”进行了重载,使之能用于两个复数的相加减。在该例中运算符重载函数operator+ ,operator-作为Complex类中的成员函数。

“+” ,”-”是双目运算符,为什么在程序中的重载函数中只有一个参数呢?实际上,运算符重载函数有两个参数,由于重载函数是Complex类中的成员函数,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员。

可以看到,重载函数operator+访问了两个对象中的成员,一个是this指针指向的对象中的成员,一个是形参对象中的成员。如this->real+c2real,this->real就是c1real。

在将运算符函数重载为成员函数后,如果出现含该运算符的表达式,如c1+c2,编译系统把它解释为c1operator+(c2)

即通过对象c1调用运算符重载函数,并以表达式中第二个参数(运算符右侧的类对象c2)作为函数实参。运算符重载函数的返回值是Complex类型,返回值是复数c1和c2之和(Complex(c1real + c2real,c1imag+c2imag))。

仔细看下吧 你的问题都在里面 这是我们的PPT

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/12185171.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存