类和对象-运算符重载

简介: 类和对象-运算符重载

C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。

重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。

当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。

您可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。

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

加号运算符重载

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

对于内置数据类型,编译器知道如何进行运算:10+10=20

两种实现方法:

  • 成员函数重载运算符
  • 全局函数重载运算符

本质:

  • 成员函数:A c = a.operator+(b)
  • 全局函数:A c = operator+(a, b)
class A
{
public:
    A operator+ (A a)//必须要有加号+
    {
        A temp;
        temp.m_a = this->m_a + a.m_a;
        temp.m_b = this->m_b + a.m_b;
        return temp;
    }
    int m_a = 10;
    int m_b = 10;
};
int main()
{
    A a;
    A b;
    //A c = a.operator+(b);
    A c = a + b;
    cout << c.m_a << endl << c.m_b << endl;
    return 0;
}
class A
{
public:
    int m_a = 10;
    int m_b = 10;
};
A operator+(A a, A b)
{
    A temp;
    temp.m_a = a.m_a + b.m_a;
    temp.m_b = a.m_b + b.m_b;
    return temp;
}
int main()
{
    A a;
    A b;
    //全局重载函数本质调用
    //A c = operator+(a, b);
    A c = a + b;
    cout << c.m_a << endl << c.m_b << endl;
    return 0;
}

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

class A
{
public:
    int m_a = 10;
    int m_b = 10;
};
A operator+(A a, A b)
{
    A temp;
    temp.m_a = a.m_a + b.m_a;
    temp.m_b = a.m_b + b.m_b;
    return temp;
}
A operator+(A a, int b)
{
    A temp;
    temp.m_a = a.m_a + b;
    temp.m_b = a.m_b + b;
    return temp;
}
int main()
{
    A a;
    A b = a + 10;
    cout << b.m_a << endl << b.m_b << endl;
    return 0;
}

总结:

  • 对于内置的数据类型的表达式的运算是不可能修改的
  • 不要滥用运算符重载:加法写成减法,乘法写成除法

左移运算符重载

  • 不会利用成员函数重载<<运算符,因为无法实现cout在左侧
  • 只能利用全局函数重载<<运算符
#include <iostream>
using namespace std;
class Person
{
    //添加友元,以访问私有属性
    friend ostream& operator<<(ostream& cout, Person& person);
private:
    string name = "张三";
    string phone = "110";
};
//cout的数据类型为ostream,返回值类型必须填ostream才能实现链式编程
//使用引用的方式,保证cout只有一个
ostream& operator<<(ostream& cout, Person& person)
{
    cout << person.name << person.phone;
    return cout;
}
int main()
{
    Person a;
    cout << a << endl;//链式编程
    return 0;
}

递增运算符重载

通过重载递增运算符,实现自己的整型数据

注意事项:

  • 前置递增要返回引用
  • 后置递增要返回值,要用int占位参数,让编译器知道是在做后置递增
class Person
{
public:
    //使用引用,为了一直对一个数据进行递增操作
    Person& operator++()//重载前置++
    {
        age += 1;
        return *this;
    }
    //不能用引用,temp局部变量会在运行结束后被销毁,非法访问
    Person operator++(int)//int代表占位参数,可以用于区分前置和后置递增
    {
        Person temp = *this;//先记录当时的结果
        age++;//后递增
        return temp;//最后将记录结果做返回
    }
    int age;
};
ostream& operator<<(ostream& cout, Person a)
{
    cout << a.age;
    return cout;
}
int main()
{
    Person a;
    a.age = 10;
    Person b;
    b.age = 10;
    cout << ++(++a) << endl;//链式编程
    cout << a.age << endl;//检验是否成功递增
    cout << b++ << endl;//链式编程
    cout << b.age << endl;//检验是否成功递增
    return 0;
}

赋值运算符重载

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

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

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

#include <iostream>
using namespace std;
class Person
{
public:
    //重载赋值运算符
    Person& operator=(Person a)
    {
        //编译器默认的浅拷贝
        //m_name = a.m_name;
        //应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
        if (m_name != NULL)
        {
            delete m_name;
            m_name = NULL;
        }
        //深拷贝
        m_name = new string(*a.m_name);
        //返回自身,以实现连等操作
        return *this;
    }
    string* m_name;
};
int main()
{
    Person a;
    a.m_name = new string("张三");
    Person b;
    b.m_name = new string("李四");
    Person c;
    c.m_name = new string("王五");
    a = b = c;
    cout << *a.m_name << *b.m_name << *c.m_name << endl;
    return 0;
}

关系运算符重载

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

对比时需要注意指针:

  • 若不加*,则对比的是指针的地址
  • 若加*,对比的是指针指向的值
#include <iostream>
using namespace std;
class Person
{
public:
    Person(string name, int age)
    {
        m_name = new string(name);
        m_age = age;
    }
    //重载关系运算符 ==
    bool operator==(Person& a)
    {
        //m_name是指针,需要加解引用操作符,否则对比的是 指针指向的地址 而不是对比 对应的值
        if (*this->m_name == *a.m_name && this->m_age == a.m_age)
        {
            return true;
        }
        return false;
    }
    int m_age;
    string* m_name;
};
int main()
{
    Person a("张三", 10);
    Person b("张三", 10);
    cout << (a == b) << endl;
    return 0;
}

函数调用运算符重载

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

由于重载后使用的方法非常像函数的调用,因此成为仿函数

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

允许匿名对象调用

class Person
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};
int main()
{
    Person a;
    cout << a(1, 2) << endl;
    //匿名对象调用
    cout << Person()(1, 2) << endl;
    return 0;
}
目录
相关文章
|
存储 缓存 算法
[转]分布式唯一ID生成方案
分布式唯一ID生成方案
617 0
[转]分布式唯一ID生成方案
|
Ubuntu 安全 Unix
Ubuntu内核OverlayFS权限逃逸漏洞(CVE-2021-3493)
Linux Kernel 一般指Linux内核。Linux是一种开源电脑操作系统内核。它是一个用C语言写成,符合POSIX标准的类Unix操作系统。
473 2
|
SQL 运维 JavaScript
Yearning目前最流行的开源数据库审核平台
Yearning帮你减小日常变更数据库的风险,规范有序记录进行数据库变更操作
2225 0
Yearning目前最流行的开源数据库审核平台
|
7月前
|
运维 Prometheus 监控
运维人别熬夜了!大模型已经能帮你盯故障了
运维人别熬夜了!大模型已经能帮你盯故障了
331 0
|
11月前
|
Web App开发 编解码 vr&ar
Deepseek解读 | UE像素流送与实时云渲染技术的差别
为了实现UE引擎开发的3D/XR程序推流,开发者通常使用像素流送(Pixel Streaming)技术。它通过WebRTC协议将服务器端渲染的画面传输到客户端,适用于短时、少并发场景。然而,在项目落地阶段,其局限性显现,实时云渲染方案成为更好的选择。Deepseek分析表明,实时云渲染具备高性能分布式渲染、低延迟传输、多平台支持等优势,特别适合高复杂度场景和大规模应用。Paraverse平行云的LarkXR产品,作为领先的实时云渲染解决方案,提供高质量、低延迟的渲染体验,支持多种3D引擎和XR内容格式,具备弹性扩展和成本优化等特点,广泛应用于元宇宙、虚拟仿真等领域。
|
机器学习/深度学习 存储 人工智能
【AI系统】自定义计算图 IR
本文介绍了模型转换的方法及流程,重点讲解了计算图的自定义方法和优化技术。通过IR(Intermediate Representation)将不同AI框架的模型转换为统一格式,实现跨平台高效部署。计算图由张量和算子构成,支持多种数据类型和内存排布格式,通过算子融合等优化技术提高模型性能。文章还详细说明了如何使用FlatBuffers定义计算图结构,包括张量、算子和网络模型的定义,为自定义神经网络提供了实践指南。
377 3
【AI系统】自定义计算图 IR
|
机器学习/深度学习 人工智能 搜索推荐
🔥解锁AI魔法!生成式大模型入门,你的“提示词”就是金钥匙🗝️
【8月更文挑战第1天】在科技浪潮中,生成式大模型作为AI领域的明星,正引领创作革命。这些模型如GPT和DALL-E,通过深度学习技术,在海量数据中学习理解与创造内容。要驾驭这些模型,关键在于设计精妙的提示词。提示词不仅是简单的指令,更是激发AI创造力的灵魂。例如,创作关于“未来教育”的文章时,“2050年个性化学习如何颠覆传统教学?”比“未来教育”能引导生成更深入、生动的内容。在图像生成方面,详细描绘场景加上情感色彩的提示词,如“星空下的古老城堡”,能使生成的图像更加引人入胜。通过不断优化提示词,我们可以开启AI无限创意的大门,见证科技与艺术的完美融合。
574 7
|
机器学习/深度学习 存储 人工智能
超级计算机是什么
【8月更文挑战第6天】超级计算机是什么
704 1
|
机器学习/深度学习 存储 算法
YOLO落地部署 | 一文全览YOLOv5最新的剪枝、量化的进展【必读】
YOLO落地部署 | 一文全览YOLOv5最新的剪枝、量化的进展【必读】
2145 0
|
域名解析 弹性计算 运维
阿里云服务器价格参考(1M-5M带宽与1年-5年活动价格)
阿里云服务器优惠价格及购买时长新鲜出炉!通过官网活动购买云服务器带宽可选1M-5M,购买时长方面既有月付的云服务器也有年付的云服务器,月付可选1个月至9个月,月付最低203.20元1个月,年付可选1年至3年或1年至5年,年付最低992.11元1年。下面是小编通过1M-5M带宽活动价格和1年-5年活动价格两个维度为大家整理汇总的阿里云服务器活动价格。
869 1
阿里云服务器价格参考(1M-5M带宽与1年-5年活动价格)