5.友元运算符重载

Posted smallqizhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5.友元运算符重载相关的知识,希望对你有一定的参考价值。

1.友元函数

 定义:在C++中,一个普通函数是不可以直接访问类中的任意成员的,但是如果把这个函数声明为友元函数,那么这个函数就可以访问类中的所有成员。  

  优点:能够不受限制地访问类中的任意成员,在一定程度上可以提高程序的执行效率。

  缺点:打破类的封装性。

  声明格式:friend 返回值数据类型 函数名(参数类别) 可以在类中的任意位置声明

  (1)普通函数声明为友元函数

class Student{
    friend void student_info(Student& student_info);
public:
    Student(){}
    ~Student(){}
protected:
private:
}

//声明函数为友元函数
void student_info(Student& stu){}

   

  (2)一个类的成员函数可以声明为另一个类的友元函数(一般不建议使用)

class Cat;//引用形参,指针,引用
class Person{
public:
    Person(Cat& c):caty(c){}
    ~Person(){}
    void show();
private:
    Cat &caty;
}

class Cat
{
public:
    Cat(){}
    ~Cat(){}
private:
    friend void show();
}

 

  (3)还可以把一个类A声明为另一个类B的友元类,这样友元类A的成员函数就可以访问类B的私有成员了。

class Cat{
public:
    Cat(){}
    ~Cat(){}
private:
    friend class Person;//声明为友元类
}

class Person{
    
}

    友元类的特点:友元类是单向的,不能被继承。

 

2.运算符重载

  算术运算符"+","-"只能用于基本数据类型(包括指针)的运算,但是对于自定义数据类型(Complex)是没有办法运算的。运算符重载之后,就可以对自定义数据类型进行运算了。

  注意事项:

    (1)运算符重载只能对已有的运算符进程重载

    (2)不能重载的运算符(::,sizeof,?:,.*,->*,.)

    (3)运算符重载不能改变运算符原来的特性和规则

  双目运算符的重载

    (1)成员函数重载  运算符的左值是函数调用者,右值是函数参数

Complex A,B;
Complex C=A+B;//重载函数 A.Complex(B)
Complex operator+(Complex B){
    Complex C;
    C.real=this->real+B.real;
    C.image=this->image+B.image;
    return C;
}

    (2)友元函数重载

Complex A,B;
Complex C=A+B;//operator(A,B)
//友元函数重载,不是成员函数,所以没有this指针
Complex operator+(Complex& A,Complex& B)
{
    Complex C;
    C.real=A.real+B.real;
    C.image=A.image+B.image;
    return C;
}

    由于友元函数不是成员函数,没有this指针,所以左右值都要通过参数传递,左值是第一个参数,右值是第二个参数。

    (3)输出重载  实质上也是友元重载

operator& operator<<(ostream& out,Complex &C){
    out<<"("<<","<<C.image<<")"<<endl;
    return out;
}

  单目运算符重载  A++是先用了再+1,++A是先+1再用

    (1)成员函数重载

      A++的情况

Complex operator++(int){
    //保存原来的值
    Complex old=*this;//==>old(*this)
    this->real+=1;
    this->image+=1;
    return lod;
}

      ++A的情况

Complex& operator++(){
    this->real+=1;
    this->image+=1
    return *this;
}

  (3)括号 [],{}重载

    (1)成员函数重载

        重载[]

int &operator[](int i){
    return this->array[i];
}

        重载()

coid operator()(){
    cout<<"()()()()()"<<endl;
}

   (4)数据类型转换重载

    (1)成员函数  格式:operator 数据类型 (){return 要转换的类型数据}

operator int*()
{
    return array
}

operator int()
{
    return length;
}

Sqlist sq(10);
int a=sq;//operaotr int();
int *p=sq;//operator int*();

    转换为自定义的数据类型

class B{
public:
    B(){}
    ~B(){}
};

class A{
public:
    A(){}
    ~A(){}
    operator B(){return b;}
    B b;
}

int main()
{
    A a;
    B b=a;
    return 0;
}

  (5).赋值运算符重载

class Data{
public:
    Data(){
        cout<<"Data()"<<endl;
        p=new int(32);
    }
    ~Data(){cout<<"~Data()"<<endl;}
    Data(Data& d){cout<<"Data(Data& d"<<endl;}
    int data;
    int *p;

    //重载赋值运算符
    Data& operator(Data& d)
    {
        if(this!= &d)//避免拷贝给自己
        {
            this->data=d.data;
            memcpy(this->p,d,p,sizeof(int));
        }
        return *this;
    }
}

int main()
{
    Data a;
    a.data=123;
    Data b=a;
    Data c;
    c=a;
    cout<<a.data<<" "<<b.data<<" "<<c.data<<endl;
    cout<<a.p<<" "<<b.p<<" "<<c.p<<endl;
    return 0;
}

 

2.构造函数隐式转换

class Number{
public:
    Number(int n=0):num(n){}
    void show(){cout<<this->number};
private:
    int num;
}

//使用
Number ynum=123;//构造函数隐式转换
ynum.show();

  想要避免隐式转换,就在构造函数前面添加"explicit"关键字

 

PS:有哪里写错写漏了,请指正,互相学习。

以上是关于5.友元运算符重载的主要内容,如果未能解决你的问题,请参考以下文章

C++入门不能重载为友元函数的4个运算符(=, ->, [ ], ( ))

运算符重载和友元函数

一元 - 使用友元函数重载运算符

类和对象——补充(运算符重载,static和explicit关键字和友元,内部类)

关于C++运算符重载和友元的概念

什么运算符一定要重载友元函数,什么时候一定要重载为成员函数?