【C++】运算符重载

目录

一、示例

二、operator

三、加减号重载

四、左移运算符重载 ( << )

五、递增运算符重载(++)

[六、赋值运算符重载 (=)](#六、赋值运算符重载 (=))

[七、关系运算符重载(> < = !=)](#七、关系运算符重载(> < = !=))

八、函数调用运算符重载

查漏补缺:


一、示例

如果我想实现以下代码,按照下面的写法是不能正常运行的。

cpp 复制代码
class Person
{
public:

    int m_A;
    int m_B;
};

Person p1;
p1.m_A = 10;
p1.m_B = 10;

Person p2;
p2.m_A = 10;
p2.m_B = 10;

Person p3;
p3 = p1 + p2;

按照以上学过的内容,可以自己写成员函数,实现两个对象相加属性后返回新对象

cpp 复制代码
Person add(Person &p)
{
    Person temp;
    temp.m_A = this -> m_A + p.m_A;
    temp.m_B = this -> m_B + p.m_B;
    return temp; //返回值会创建一个新的对象出来
}
二、operator

编译器起一个通用重载的名称:operator

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

注意:

①对于内置的数据类型的表达式的运算符是不可能改变的:int、float、double

②不要滥用运算符重载:把加法写成减法...

三、加减号重载

* 通过成员函数重载 + 号运算符

cpp 复制代码
class Person
{
public:
    
    Person operator+(Person &p)
    {
        Person temp;
        temp.m_A = this -> m_A + p.m_A;
        temp.m_B = this -> m_B + p.m_B;
        return temp; //返回值会创建一个新的对象出来
    }

    int m_A;
    int m_B;
    
};

void test()
{
    Person p1;
    p1.m_A = 10;
    p1.m_B = 10;

    Person p2;
    p2.m_A = 10;
    p2.m_B = 10;
    
    //原理:Person p3 = p1.operator+(p2);
    //简化如下:
    Person p3 = p1 + p2;
}

* 通过全局函数重载 + 号运算符

cpp 复制代码
class Person
{
public:

    int m_A;
    int m_B;
    
};

Person operator+ (Peerson &p1, Person &p2)
{
    Person temp;
    temp.m_A = p1.m_A + p2.m_A;
    temp.m_B = p1.m_B + p2.m_B;
    return temp;
}

void test()
{
    Person p1;
    p1.m_A = 10;
    p1.m_B = 10;

    Person p2;
    p2.m_A = 10;
    p2.m_B = 10;
    
    //原理:Person p3 = operator+ (p1,p2);
    //简化如下:
    Person p3 = p1 + p2;
}

* 运算符函数重载

cpp 复制代码
class Person
{
public:

    int m_A;
    int m_B;
    
};

Person operator+ (Peerson &p1, int num)
{
    Person temp;
    temp.m_A = p1.m_A + num;
    temp.m_B = p1.m_B + num;
    return temp;
}

void test()
{
    Person p1;
    p1.m_A = 10;
    p1.m_B = 10;

    //原理:Person p3 = operator+ (p1,num);
    //简化如下:person + int
    Person p3 = p1 + 10 ;
}
四、左移运算符重载 ( << )

* 使得cout可以输出person类数据

cpp 复制代码
class Person
{
    friend ostream & operator<<(ostream &cout,Person p);

public:
    Person(int a, int b)
    {
        m_A = a;
        m_B = b;
    }

private:

    //利用成员函数来重写左移运算符
    //如果不知道该函数应该返回什么 可以先写一个void做测试
    //通常不会使用成员函数重载<<运算符,因为无法实现 cout在左侧 会出现 p << cout 的简化方式
    //void operator<<( cout )
    //{}
    
    int m_A;
    int m_B;
};

//只能利用全局函数重载左移运算符
//不清楚cout是什么类型,可以右键跳转定义
//ostream标准输出流对象,因为全局只有一个,所以需要用引用方式传过来
ostream & operator<<(ostream &cout,Person p) //本质:operator<< (cout,p) 简化形式:cout << p
{
    cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
    return cout;
}

void test()
{
    Person p(10,10);

    //调用完返回cout就可以链式编程不断追加
    cout << p << endl;
}
五、递增运算符重载(++)

可以利用该方法写一个int数据类型

** 注意前置递增和后置递增的返回类型区别

cpp 复制代码
class MyInt
{

    friend ostream& operator<<(ostream& cout,MyInt mint);

public:
    MyInt()
    {
        m_Num = 0;
    }

    //成员函数重载前置++运算符
    //返回引用不返回值,为了一直对一个数据进行递增操作,而非对一个新的数据进行操作
    MyInt& operator++()
    {
        //先进行++运算
        m_Num++;
        //再将自身作为返回
        return *this; //this指向自身,*将其解引用
    }

    //成员函数重载后置++运算符
    //int代表的是占位参数,用于区分前置和后置递增,只能写int其他不行
    //后置需要返回值,不能返回应用,因为temp是局部对象,返回引用是非法操作
    MyInt operator++(int)
    {
        //先返回结果(记录当时结果)
        MyInt temp = *this;
        //再进行递增
        m_Num++;
        //最后将结果返回
        return temp;
    }

private:
    int m_Num;

};

ostream& operator<<(ostream& cout,MyInt mint)
{
    cout << mint.m_Num;
    return cout;
}

void test()
{
    MyInt mint;
    cout << mint << endl; // 0
    cout << ++mint << endl; // 1
    cout << mint++ << endl; // 1
    cout << mint << endl; // 2
}
六、赋值运算符重载 (=)

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

①默认构造函数:无参,函数体为空

②默认析构函数:无参,函数体为空

③默认拷贝构造函数:对属性进行值拷贝

④赋值运算符operator=,对属性进行值拷贝

cpp 复制代码
class Person
{
public:

    Person(int age)
    {
        m_Age = new int(age); //将age数据创建在堆区,并使用指针维护该数据
    }

    //堆区数据由程序员手动创建及释放
    ~Person()
    {
        if(m_Age != NULL)
        {
            delete m_Age;
            m_Age = NULL;
        }
    }

    int *m_Age;
};

void test()
{
    Person p1(18);
    Person p2(20);

    //该方法为浅拷贝 会出现p1p2重复释放 程序崩溃
    p2 = p1;
    //利用深拷贝解决该问题

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

    cout << "p2的年龄为:" << *p2.m_Age << endl;
}

** 重载赋值运算符

cpp 复制代码
class Person
{
public:

    Person(int age)
    {
        m_Age = new int(age); //将age数据创建在堆区,并使用指针维护该数据
    }

    //重载赋值运算符
    Person& operator=(Person &p)
    {
        //编译器提供的是浅拷贝:m_Age = p.m_Age; 不可取
        //先判断是否有属性在堆区,如果有需要先释放干净,再深拷贝
        if(m_Age != NULL)
        {
            dekete m_Age;
            m_Age = NULL;
        }

        m_Age = new(*p.m_Age);
        return *this;
    }


    //堆区数据由程序员手动创建及释放
    ~Person()
    {
        if(m_Age != NULL)
        {
            delete m_Age;
            m_Age = NULL;
        }
    }

    int *m_Age;
};

void test()
{
    Person p1(18);
    Person p2(20);
    Person p3(30);
   
    cout << "p1的年龄为:" << *p1.m_Age << endl;

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

    cout << "p3的年龄为:" << *p3.m_Age << endl;
}
七、关系运算符重载(> < = !=)

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

cpp 复制代码
class Person
{
public:

    Person(string name, int age)
    {
        this->m_Name = name;
        this->m_Age = age;
    };

    //重载关系运算符==号
    bool operator==(Person &p)
    {
        if(this->m_Name == p.m_Name && this->m_Age == p.Age)
        {
            return true;
        }
            return false;
    }

    //重载关系运算符!=号
    bool operator==(Person &p)
    {
        if(this->m_Name == p.m_Name && this->m_Age == p.Age)
        {
            return false;
        }
            return true;
    }

    string m_Name;
    int m_Age;
    
};

void test()
{
    Person p1("Tom", 18);
    Person p2("Tom", 18);

    if(p1 == p2)
    {
        cout << "p1和p2是相等的" << endl;
    }
    else
    {
        cout << "p1和p2是不相等的" << endl;
    }
    
}
八、函数调用运算符重载

①函数调用运算符()可以重载

②由于重载后使用的方法像函数的调用,故称为仿函数

③仿函数没有固定写法

cpp 复制代码
class MyPrint
{
public:

    void operator()(string text)
    {
        cout << text << endl;
    }

};

void test01()
{
    //重载()操作符,仿函数
    MyPrint myFunc;
    myFunc("hello!");
}

class MyAdd
{
public:

    int operator()(int num1, int num2)
    {
       return num1 + num2;
    }
};

void test02()
{
    MyAdd myadd;
    int ret = myadd(1,2);
    cout << "ret=" << ret << endl;

    //匿名函数对象
    cout << MyAdd()(100, 100) << endl;
}
查漏补缺:

函数重载和函数重写的区别:https://blog.csdn.net/inter_peng/article/details/53940179

递增运算符复习:

cpp 复制代码
int a = 10;
cout << ++a << endl; // 11
cout << a << endl; //11

int b = 10;
cout << b++ << endl; //10
cout << b << endl; //11

new关键字使用方法:https://blog.csdn.net/qq_15345177/article/details/88066050

相关推荐
小奶包他干奶奶4 小时前
Webpack学习——Loader(文件转换器)
前端·学习·webpack
小奶包他干奶奶4 小时前
Webpack学习——原理理解
学习·webpack·devops
励志成为美貌才华为一体的女子4 小时前
强化学习PPO和GRPO逻辑学习
学习
tobebetter95274 小时前
How to manage python versions on windows
开发语言·windows·python
meichaoWen5 小时前
【Vue3】vue3的全面学习(一)
前端·javascript·学习
FFF团团员9095 小时前
树莓派学习笔记3:LED和Button
笔记·学习
9***P3345 小时前
PHP代码覆盖率
开发语言·php·代码覆盖率
CoderYanger5 小时前
优选算法-栈:67.基本计算器Ⅱ
java·开发语言·算法·leetcode·职场和发展·1024程序员节
碧海潮生_CC5 小时前
【CUDA笔记】04 CUDA 归约, 原子操作,Warp 交换
笔记·cuda
jllllyuz5 小时前
Matlab实现基于Matrix Pencil算法实现声源信号角度和时间估计
开发语言·算法·matlab