C++核心编程之类和对象--C++运算符重载

目录

一、运算符重载

二、加号运算符重载

三、左移运算符重载

将类中的成员设置为私有属性,将全局函数设置为友元访问类中的成员

四、递增运算符

五、赋值运算符重载

六、关系运算符重载

七、函数调用运算符重载


一、运算符重载

对已有的运算符进行重新定义,赋予其另一种功能,以适应不同的数据类型

二、加号运算符重载

作用:实现两个自定义数据相加的运算

是自定义的一个函数作用,函数的名称替换成编译器统一提供的名字

运算符重载也可以发生函数重载

函数名 替换成 : operator+

总结注意:

  1. 对于内置的数据类型的表达式的运算符是不可能改变的
  2. 不可以滥用运算符重载

示例:

#include<iostream>

using namespace std;

// 加号运算符重载

class person {

public:

    // 1.成员函数重载

    person operator+(person& p)

    {

        person temp;

        temp.A = this->A + p.A;

        temp.B = this->B + p.B;

        return temp;

    }

int A;

int B;

};

// 2.全局函数重载+号

person operator+(person& p1, person& p2)

{

    // 全局函数的本质调用是:

    // person p3 = operator+(p1,p2);

    person temp1;

    temp1.A = p1.A + p2.A;

    temp1.B = p1.B + p2.B;

    return temp1;

}

// 运算符重载也可以发生函数重载

person operator+(person& p1, int num)

{

    person temp1;

    temp1.A = p1.A + num;

    temp1.B = p1.B + num;

    return temp1;

}



void test01()

{

    person p1;

    p1.A = 10;

    p1.B = 10;

    person p2;

    p2.A = 10;

    p2.B = 10;



    // 成员函数的本质调用是

    person p3 = p1.operator+(p2);

    cout << "成员函数的运算符重载调用后:" << endl << "p3.A:" << p3.A << "\tp3.B:" << p3.B << endl;



    // 全局函数重载的本质调用

    person p4 = operator+(p1,p2);

    cout << "全局函数的运算符重载调用后:" << endl << "p4.A:" << p4.A << "\tp4.B:" << p4.B << endl;



    // 成员函数与全局函数都可以用以下方式直接相加

    //person p6 = p1 + p2;

    //cout << "p3的A的值:" << p3.A << endl << "p3的B的值:" << p3.B << endl;



    //函数重载

    person p5 = p1 + 5;

    cout << "函数重载完后p5的A的值:" << p5.A << endl << "p5的B的值:" << p5.B << endl;



}

int main()

{

    test01();

    return 0;

}

运行结果:

三、左移运算符重载

作用:可以实现输出自定义类型

总结:重载左移运算符配合友元可以实现输出自定义数据类型。

示例:

#include<iostream>

using namespace std;

// 左移运算符重载

class person {

public:

    // 1.成员函数重载左移运算符

    // 利用成员函数重载  左移运算符  p.operator<<(cout)  简化版本是: p<<cout

    // 一般不利用成员函数重载左移运算符,因为无法实现cout在左侧

    // 实现的方式是p << cout

    int A;

    int B;

};

// 2.全局函数重载左移运算符

ostream& operator<<(ostream& cout, person& p)

{

    // ostream 是输出流

    cout << "A = " << p.A << endl << "B = " << p.B << endl;

    return cout;// 返回的还是输出流对象,为了能够链式编程

}

    // cout重载完再返回cout,在重载调用完后还可以继续输出

    // return cout 或者 out 都是可以的, 用引用的方式调用,out本质上是cout的一个别名

void test01()

{

    person p1;

    p1.A = 10;

    p1.B = 10;

    cout << p1 << "Hello World!" << endl;

}

int main()

{

    test01();

    return 0;

}

运行结果:

将类中的成员设置为私有属性,将全局函数设置为友元访问类中的成员

示例:

#include<iostream>

using namespace std;

// 左移运算符重载

class person {

    friend ostream& operator<<(ostream& cout, person& p);

public:

    person(int a,int b)

    {

        this->A = a;

        this->B = b;

    }

private:

    // 1.成员函数重载左移运算符

    // 利用成员函数重载  左移运算符  p.operator<<(cout)  简化版本是: p<<cout

    // 一般不利用成员函数重载左移运算符,因为无法实现cout在左侧

    // 实现的方式是p << cout

    int A;

    int B;

};

// 2.全局函数重载左移运算符

ostream& operator<<(ostream& cout, person& p)

{

    // ostream 是输出流

    cout << "A = " << p.A << endl << "B = " << p.B << endl;

    return cout;// 返回的还是输出流对象,为了能够链式编程

}

// cout重载完再返回cout,在重载调用完后还可以继续输出

// return cout 或者 out 都是可以的, 用引用的方式调用,out本质上是cout的一个别名

void test01()

{

    person p1(100,100);

    cout << p1 << "Hello World!" << endl;

}

int main()

{

    test01();

    return 0;

}

运行结果:

四、递增运算符

 前置递增返回引用,后置递增返回值

示例:

#include<iostream>

#include<math.h>

using namespace std;

// 重载递增运算符



// 自定义整形

class my_Integer {

    friend ostream& operator<< (ostream& cout, my_Integer myint);

public:

    my_Integer()

    {

        my_num = 0;

    }

    // 重置前置++运算符

    my_Integer& operator++()

    {

        my_num++; // 进行++

        return *this;  // 返回自身

        // 返回引用是为了一直对一个数进行操作

    }



    // 重置后置++运算符

    // 后置++不能返回引用是因为不能返回局部变量

    my_Integer  operator++(int) // int 代表是占位参数  可以用于区分  前置和后置递增

    {

        // 先记录

        my_Integer temp = *this;

        // 后递增

        my_num++;

        // 最后将记录的结果返回

        return temp;

    }

private:

    int my_num;

};



// 重载左移运算符

ostream& operator<< (ostream& cout, my_Integer myint)

{

    cout << myint.my_num;

    return cout;

}



// 前置++

void test01()

{

    my_Integer myint;

    cout << "myint1,前置++" << endl << "++(++myprint) = " << ++(++myint) << " myprint = " << myint << endl;

}



// 后置++

void test02()

{

    my_Integer myint2;

    cout << "myint2,后置++" << endl << "(myprint2++) = " << myint2++ << " myprint2 = " << myint2 << endl;

}



int main()

{

    int a = 10;

    cout << "后置++,先输出数据,再++" << endl;

    cout << a++ << endl;

    cout << a << endl;



    int b = 10;

    cout << "前置++,输出++结果" << endl;

    cout << ++b << endl;

    cout << b << endl;



    test01();

    test02();

    return 0;

}

运行结果:

 

五、赋值运算符重载

C++编译器至少给一个类添加4个函数:

  1. 默认构造函数   (无参,函数体为空)
  2. 默认析构函数   (无参,函数体为空)
  3. 默认拷贝构造函数  (对属性进行拷贝)
  4. 赋值运算符  operator=,  对属性进行值拷贝(浅拷贝)

作用:如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题。

示例:

#include<iostream>

#include<math.h>

using namespace std;

// 重载赋值运算符

class person{

public:

    person(int age)

    {

        m_age = new int (age);

    }

    ~person()

    {

        if(m_age!=NULL)

        {

            delete m_age;

            m_age = NULL;
        
        }

    }

    // 重载 赋值运算符

    person & operator=(person & p)// 链式编程的思想,需要返回本身

    {

        // 编译器提供的是两个指针指向同一个地址,在堆区的内容释放的时候只能释放一次,而引起的深,浅拷贝的问题

        // m_age = p.m_age;

        // 编译器提供的是浅拷贝,导致拷贝得到的是堆区地址,堆区的空间只能释放一次,而浅拷贝导致释放两次

 

        // 应该先判断是否有属性在堆区,如果有先释放然后深拷贝

        if(m_age!=NULL){

            delete m_age;

            m_age=NULL;

        }

        // 深拷贝的操作

        m_age = new int(*p.m_age);

        // 返回自身

        return *this;

    }

    int *m_age;

};

 

void test01()

{

    person p(18) ;

    cout<<"p的年龄:"<<*p.m_age<<endl;

    person p1(20);

    cout<<"p1的年龄:"<<*p1.m_age<<endl;

    person p2(10);

    cout<<"p2的年龄:"<<*p2.m_age<<endl;

    cout<<"-------------------------------"<<endl;

 

    cout<<"重载完=后:"<<endl;

    p2=p1=p; // 返回的是自身,可以连等

    cout<<"p的年龄:"<<*p.m_age<<endl;

    cout<<"p1的年龄:"<<*p1.m_age<<endl;

    cout<<"p2的年龄:"<<*p2.m_age<<endl;

}

int main()

{

    test01();

    return 0;

}

运行结果:

 

六、关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

示例:

#include<iostream>

#include<math.h>

using namespace std;

// 重载关系运算符

class person {

public:

    person(string name, int age)

    {

        this->name = name;

        this->age = age;

    }

    // 重载==号

    bool operator==(person& p)

    {

        if (this->name == p.name && this->age == p.age)

        {

            return true;

        }

        return false;

    }
    
    // 重载不等号



    bool operator!=(person &p)

    {

        if(this->name == p.name && this->age == p.age)

        {

            return false;

        }

        return true;

    }



    string name;

    int age;

};



void test01()

{

    person p("TOM", 18);

    cout << "p的姓名:" << p.name << " p的年龄:" << p.age << endl;



    person p1("TOM", 20);

    cout << "p1的姓名:" << p1.name << " p1的年龄:" << p1.age << endl;

    person p2("TOM", 18);

    cout << "p2的姓名:" << p2.name << " p2的年龄:" << p2.age << endl;



    cout << "比较p与p1-------------------------" << endl;

    cout << "重载==后的判断:" << endl;

    if (p == p1) {

        cout << "p和p1是相等的" << endl;

    }

    else {

        cout << "p和p1是不相等的" << endl;

    }



    cout << "重载!=后的判断:" << endl;

    if(p!=p1){

        cout<<"p和p1是不相等的"<<endl;

    }else{

        cout<<"p和p1是相等的"<<endl;

    }

    cout << "比较p与p2-------------------------" << endl;

    cout << "重载==后的判断:" << endl;

    if (p == p2) {

        cout << "p和p2是相等的" << endl;

    }

    else {

        cout << "p和p2是不相等的" << endl;

    }

}

int main()

{

    test01();

    return 0;

}

运行结果:

 

七、函数调用运算符重载

  •  函数调用运算符()也可以重载
  •  重载后的使用方式与函数的调用十分相似,因此称为仿函数
  •  仿函数没有固定的写法,非常灵活

示例:

#include<iostream>

#include<math.h>

using namespace std;

// 函数调用运算符重载

class my_print{

public:

    // 重载函数调用运算符

    void operator()(string test)

    {

        cout<<test<<endl;

    }

};

// 仿函数非常灵活,没有固定的写法

 

void myprint02(string test)

{

    cout<<test<<endl;

}

 

// 一个加法的类

class myadd{

public:

    int operator()(int num1,int num2)

    {

        return num1+num2;

    }

};

 

 

void test01()

{

    my_print mprint;

    // 使用起来特别类似函数调用,因此称为仿函数

 

    mprint("hello 重载函数调用运算符");// 重载了()类似于函数

 

    myprint02("函数也可以直接放入字符串");

}

void test02()

{

    myadd myADD;

    int ret = myADD(10,20);

    cout<<"自定义加法类的仿函数结果:"<<ret<<endl;

 

    // 匿名函数对象 myadd(),使用完成后立即自动释放

    cout<<myadd()(100,100)<<endl;

}

int main()

{

    test01();

    test02();

    return 0;

}

运行结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值