记录C++学习 16

embedded/2024/12/29 22:51:46/

运算符及其重载

运算符

运算符实际就是函数

C++中的运算符有

+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= <=> && || ++ -- , ->* 

-> ( ) [ ]

运算符的重载

重载本质上是给运算符重新赋予新的含义

运算符的重载应该很少使用

举例

在不用运算符重载的情况下,我们可以这样相加两个向量,需要写个函数

#include <iostream>

struct Vector
{
    float x, y;
    Vector(float x, float y)
        :x(x),y(y)
    {

    }
    Vector Add(const Vector& other)const
    {
        return Vector(x + other.x, y + other.y);
    }

};

int main()
{
    Vector position(2.0f, 3.0f);
    Vector speed(0.5f, 1.0f);
    Vector result = position.Add(speed);
    std::cout << result.x<<result.y << std::endl;
    std::cin.get();

}

重载+运算符 

通过使用运算符重载我们可以修改代码如下

#include <iostream>

struct Vector
{
    float x, y;
    Vector(float x, float y)
        :x(x),y(y)
    {

    }
    Vector Add(const Vector& other)const
    {
        return Vector(x + other.x, y + other.y);
    }
    Vector operator+ (const Vector& other)const
    {
        return Add(other);
    }

};

int main()
{
    Vector position(2.0f, 3.0f);
    Vector speed(0.5f, 1.0f);
    Vector result = position+speed;
    std::cout << result.x<<result.y << std::endl;
    std::cin.get();

}

重载<<运算符

我们也可以修改<<运算符,代码如下

#include <iostream>

struct Vector
{
    float x, y;
    Vector(float x, float y)
        :x(x),y(y)
    {

    }
    Vector Add(const Vector& other)const
    {
        return Vector(x + other.x, y + other.y);
    }
    Vector operator+ (const Vector& other)const
    {
        return Add(other);
    }

};
std::ostream& operator<<(std::ostream& stream, const Vector other)
{
    stream << other.x << other.y;
    return stream;
}

int main()
{
    Vector position(2.0f, 3.0f);
    Vector speed(0.5f, 1.0f);
    Vector result = position+speed;
    std::cout << result<< std::endl;
    std::cin.get();

}

重载运算符会降低代码可读性,所以尽量不要这样做 

重载==运算符

result1和result2是两个实例化对象,不能通过==运算符比较,但我们可以重载==运算符

 #include <iostream>

struct Vector
{
    float x, y;
    Vector(float x, float y)
        :x(x),y(y)
    {

    }
    Vector Add(const Vector& other)const
    {
        return Vector(x + other.x, y + other.y);
    }
    Vector operator+ (const Vector& other)const
    {
        return Add(other);
    }
    bool operator==(const Vector& other)const
    {
        return x == other.x && y == other.y;
    }

};
std::ostream& operator<<(std::ostream& stream, const Vector other)
{
    stream << other.x << other.y;
    return stream;
}

int main()
{
    Vector position(2.0f, 3.0f);
    Vector speed(0.5f, 1.0f);
    Vector result1 = position.Add(speed);
    Vector result2 = position+speed;
    if (result1 == result2)
    {

    }
    std::cout << result1<< std::endl;
    std::cin.get();

}

补充 

以下关于运算符及重载运算符有更为详细的解释
运算符重载 - cppreference.comicon-default.png?t=O83Ahttps://en.cppreference.com/w/cpp/language/operators

this关键字 

通过this可以访问成员函数,成员函数即属于某个类的函数或方法,在内部方法中我们可以引用this

this是一个指向当前对象实例的指针

举例

通过this调用类中当前方法外的变量

当我们在类中赋值时,可以采用成员初始化列表,代码如下

#include <iostream>

class Entity
{
public:
    int x, y;
    Entity(int x, int y)
        :x(x),y(y)
    {
        
    }
};

int main()
{
    Entity e(1,2);
    std::cin.get();

}

但如果我想在函数内部写,类中的x变量和构造函数的x重复了 ,我们可以使用this关键字,this是一个指向当前对象实例的指针,修改代码如下

#include <iostream>

class Entity
{
public:
    int x, y;
    Entity(int x, int y)
    {
        (*this).x = x;
        (*this).y = y;
    }
};

int main()
{
    Entity e(1,2);
    std::cin.get();

}

在日常使用中我们通过->来代替

#include <iostream>

class Entity
{
public:
    int x, y;
    Entity(int x, int y)
    {
        this->x;
        this->y;
    }
};

int main()
{
    Entity e(1,2);
    std::cin.get();

}

通过this调用类以外的函数

因为this本质上是指针,而Printentity()需要传入实例化对象,所以要用*解引用

在类中用Printentity()所以要在void Printentity(const Entity& e);前做class Entity;的前置声明

#include <iostream>
class Entity;
void Printentity(const Entity& e);

class Entity
{
public:
    int x, y;
    Entity(int x, int y)
    {

        this->x;
        this-> y;
        Printentity(*this);
    }
    int Getx()const
    {
        return x;
    }
};
void Printentity(const Entity& e)
{

}

int main()
{
    Entity e(1,2);
    std::cin.get();

}

对象的生存期(栈作用域生存期)

栈可以认为是一种数据结构,可以在上面堆叠一些东西,就像桌子上的一堆书,你访问其中一本,需要把上面的先拿出来

一旦作用域结束,你把这本书拿出来,然后扔掉,你在书里写的基于栈的变量、所创造的对象就全消失了

举例

#include <iostream>


class Entity
{
private:
    int x;
public:
    Entity()
    {
        std::cout << "create entity" << std::endl;
    }
    ~Entity()
    {
        std::cout << "destroy entity" << std::endl;
    }

};

int main()
{
    {
        Entity e;
    }
    std::cin.get();
}

结果

create entity
destroy entity 

当将e在堆上创建,修改代码如下

 #include <iostream>


class Entity
{
private:
    int x;
public:
    Entity()
    {
        std::cout << "create entity" << std::endl;
    }
    ~Entity()
    {
        std::cout << "destroy entity" << std::endl;
    }

};

int main()
{
    {
        Entity* e=new Entity();
    }
    std::cin.get();
}

结果

create entity 

 所以在栈上创建一个变量,超出范围后,就会消失

作用域指针

利用栈内存的释放机制控制堆内存,而不用手动调用delete来释放内存,因为一旦超出作用域会自动调用delete释放内存

#include <iostream>

class Entity
{
private:
    int x;
public:
    Entity()
    {
        std::cout << "create entity" << std::endl;
    }
    ~Entity()
    {
        std::cout << "destroy entity" << std::endl;
    }
};

class Scopedptr
{
private:
    Entity* m_ptr;
public:
    Scopedptr(Entity* ptr)
        :m_ptr(ptr)
    {
    }
    ~Scopedptr()
    {
        delete m_ptr;
    }
};

int main()
{
    {
        Scopedptr e(new Entity());
    }
    std::cin.get();
}

结果

create entity
destroy entity 

 使用new关键字调用堆内存,结果得到调用栈内存一样的结果

此时Scopedptr对象e为栈上分配的,当自动消灭时调用析构函数 ~Scopedptr(),删除m_ptr,而m_ptr是堆上对象,被删除后自动调用~Entity()


http://www.ppmy.cn/embedded/148801.html

相关文章

预览和下载 (pc和微信小程序)

1.微信小程序 预览pdf 或者 图片等 //utils.js 文件//通过接口返回文件链接 打开文档 export default function previewFile({ downLinkUrl, tempFilePath }) {let url "https://" downLinkUrl.replace("http://", "").replace("https:…

关于小程序内嵌h5打开新的小程序

关于小程序内嵌h5打开新的小程序 三种方式 https://juejin.cn/post/7055551463489011749 只依赖于h5本身的就是 https://huaweicloud.csdn.net/64f97ebb6b896f66024ca16c.html https://juejin.cn/post/7055551463489011749 navigateToMiniProgram 故小程序webview里的h5无法…

[Unity Shader]【图形渲染】 数学基础10 - 旋转矩阵

在计算机图形学和着色器开发中,旋转矩阵是处理物体旋转操作的核心工具之一。旋转操作是三维变换中相对复杂的一部分,主要通过线性代数中的矩阵运算实现。本篇文章将系统介绍三种围绕坐标轴的旋转矩阵的定义和性质。 1. 什么是旋转矩阵? 旋转矩阵是用于将点绕某个轴旋转一定…

云手机与Temu矩阵:跨境电商运营新引擎

云手机与 Temu 矩阵结合的基础 云手机技术原理 云手机基于先进的 ARM 虚拟化技术&#xff0c;在服务器端运行 APP。通过在服务器上利用容器虚拟化软件技术&#xff0c;能够虚拟出多个独立的手机操作系统实例&#xff0c;每个实例等同于一部单独的手机&#xff0c;可独立运行各…

Saprk和Flink的区别

1 、设计理念方面 Spark 的技术理念是使用微批来模拟流的计算&#xff0c;基于 Micro-batch &#xff0c;数据流以时间为单位被切分为一个个 批次&#xff0c;通过分布式数据集RDD 进行批量处理&#xff0c;是一种伪实时。 Flink 是基于事件驱动的&#xff0c;是面向流的处理…

Flink 的并行度配置低于Kafka 分区数会出现的问题

在 Flink 中使用 Kafka 数据源时&#xff0c;设置的 Kafka 分区数 和 Flink 的并行度 会直接影响数据的处理方式。如果你的 Kafka 分区数大于 Flink 的并行度&#xff0c;可能会引发以下问题&#xff1a; 1. Kafka 分区与 Flink 任务不匹配 Flink 在读取 Kafka 数据时&#xf…

Redis热点数据管理全解析:从MySQL同步到高效缓存的完整解决方案

1. 引言 1.1 背景介绍&#xff1a;MySQL与Redis在高性能场景下的结合 在现代互联网应用中&#xff0c;MySQL作为关系型数据库&#xff0c;承担了大量业务数据的存储任务。然而&#xff0c;随着业务的增长&#xff0c;海量数据的查询性能成为一个瓶颈。为了应对高并发和低延迟…

OpenMV与STM32通信全面指南

目录 引言 一、OpenMV和STM32简介 1.1 OpenMV简介 1.2 STM32简介 二、通信协议概述 三、硬件连接 3.1 硬件准备 3.2 引脚连接 四、软件环境搭建 4.1 OpenMV IDE安装 4.2 STM32开发环境 五、UART通信实现 5.1 OpenMV端编程 5.2 STM32端编程 六、SPI通信实现 6.1…