当前位置: 首页 > article >正文

C++ 中的运算符重载(二)

运算符重载的实例和应用

运算符重载是一种非常实用和有趣的特性,它可以让我们对自定义类型的数据进行各种操作,从而实现一些复杂和高级的功能。下面我们就来介绍一些运算符重载的实例和应用,以及它们的代码和效果:

  • 重载赋值运算符=,用于实现对象的拷贝赋值。赋值运算符=是一种特殊的运算符,它可以对任何类型的数据进行赋值操作,即将右操作数的值赋给左操作数。但是,如果我们想要对自定义类型的数据进行赋值操作,例如类的对象,那么我们就需要重载赋值运算符=,以便实现对象的拷贝赋值,即将右操作数对象的所有成员变量的值赋给左操作数对象的对应成员变量。这样,我们就可以实现对象的深拷贝,而不是浅拷贝,避免出现一些潜在的问题,例如内存泄漏、空指针、重复释放等。例如,我们可以定义一个String 类来表示字符串,然后重载赋值运算符=,用于实现字符串的拷贝赋值。代码如下:
// 定义String 类
class String {
public:
    // 构造函数,用于初始化字符串对象
    String(const char* str = "") {
        // 如果参数为空字符串,就将指针指向一个空字符,否则就动态分配内存并拷贝字符串
        if (str == "") {
            this->str = new char[1];
            this->str[0] = '\0';
        } else {
            this->str = new char[strlen(str) + 1];
            strcpy(this->str, str);
        }
    }
    // 拷贝构造函数,用于初始化字符串对象
    String(const String& s) {
        // 动态分配内存并拷贝字符串
        this->str = new char[strlen(s.str) + 1];
        strcpy(this->str, s.str);
    }
    // 析构函数,用于释放字符串对象
    ~String() {
        // 释放动态分配的内存
        delete[] this->str;
    }
    // 重载赋值运算符,用于实现字符串的拷贝赋值
    String& operator=(const String& s) {
        // 如果左操作数和右操作数是同一个对象,就直接返回左操作数的引用,避免自赋值的错误
        if (this == &s) {
            return *this;
        }
        // 释放左操作数原有的内存
        delete[] this->str;
        // 动态分配新的内存并拷贝字符串
        this->str = new char[strlen(s.str) + 1];
        strcpy(this->str, s.str);
        // 返回左操作数的引用,以便进行连续赋值
        return *this;
    }
    // 声明友元函数,用于输出字符串对象
    friend std::ostream& operator<<(std::ostream& out, const String& s);
private:
    // 私有成员变量,用于存储字符串的指针
    char* str;
};

// 定义友元函数,用于输出字符串对象
std::ostream& operator<<(std::ostream& out, const String& s) {
    // 输出字符串的内容
    out << s.str;
    // 返回输出流对象,以便进行连续输出
    return out;
}

// 主函数,用于测试
int main() {
    // 创建两个字符串对象
    String s1("Hello");
    String s2("World");
    // 使用赋值运算符对字符串进行拷贝赋值,并输出结果
    std::cout << (s1 = s2) << std::endl; // 输出结果为:World
    // 使用赋值运算符对字符串进行连续赋值,并输出结果
    std::cout << (s1 = s2 = "Bing") << std::endl; // 输出结果为:Bing
    return 0;
}

从上面的代码可以看出,重载赋值运算符=可以让我们对字符串对象进行拷贝赋值,就像对内置类型的数据进行赋值一样。这样,我们就可以实现字符串对象的深拷贝,避免出现一些潜在的问题,例如内存泄漏、空指针、重复释放等。

  • 重载插入运算符<<和提取运算符>>,用于实现对象的输入和输出。插入运算符<<和提取运算符>>是两种特殊的运算符,它们可以对标准输入流std::cin和标准输出流std::cout进行操作,实现数据的输入和输出。但是,如果我们想要对自定义类型的数据进行输入和输出,例如类的对象,那么我们就需要重载插入运算符<<和提取运算符>>,以便实现对象的输入和输出,即将对象的内容输出到标准输出流,或者从标准输入流读取数据并赋给对象。这样,我们就可以实现对象的交互和显示,提高用户的体验和友好性。例如,我们可以定义一个Point 类来表示二维平面上的点,然后重载插入运算符<<和提取运算符>>,用于实现点的输入和输出。代码如下:
// 定义Point 类
class Point {
public:
    // 构造函数,用于初始化点对象
    Point(int x = 0, int y = 0) {
        this->x = x;
        this->y = y;
    }
    // 声明友元函数,用于重载插入运算符
    friend std::ostream& operator<<(std::ostream& out, const Point& p);
    // 声明友元函数,用于重载提取运算符
    friend std::istream& operator>>(std::istream& in, Point& p);
private:
    // 私有成员变量,用于存储点的横坐标和纵坐标
    int x;
    int y;
};

// 定义友元函数,用于重载插入运算符
std::ostream& operator<<(std::ostream& out, const Point& p) {
    // 输出点的横坐标和纵坐标,用括号和逗号分隔
    out << "(" << p.x << ", " << p.y << ")";
    // 返回输出流对象,以便进行连续输出
    return out;
}

// 定义友元函数,用于重载提取运算符
std::istream& operator>>(std::istream& in, Point& p) {
    // 从输入流读取两个整数,并赋给点的横坐标和纵坐标
    in >> p.x >> p.y;
    // 返回输入流对象,以便进行连续输入
    return in;
}

// 主函数,用于测试
int main() {
    // 创建一个点对象
    Point p1;
    // 使用提取运算符对点进行输入,并输出结果
    std::cout << "Please enter a point: ";
    std::cin >> p1;
    std::cout << "The point you entered is: " << p1 << std::endl;
    // 例如,输入:1 2
    // 输出结果为:The point you entered is: (1, 2)
    return 0;
}

从上面的代码可以看出,重载插入运算符<<和提取运算符>>可以让我们对点对象进行输入和输出,就像对内置类型的数据进行输入和输出一样。这样,我们就可以实现点对象的交互和显示,提高用户的体验和友好性。


http://www.kler.cn/a/159877.html

相关文章:

  • 探索 Seata 分布式事务
  • Spring Boot 的核心注解
  • 【面试分享】xshell连接Linux服务器22端口执行命令top期间的技术细节和底层逻辑
  • Ubuntu 22 安装 Apache Doris 3.0.3 笔记
  • spring-data-jpa 一对多,多对一,多对多
  • 《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接
  • 【Web】NewStarCTF Week3 个人复现
  • centos7 yum安装jdk1.8
  • Go 模块系统最小版本选择法 MVS 详解
  • 编译器缓存
  • 多线程(初阶七:阻塞队列和生产者消费者模型)
  • SQL 错误 [1476] [22012]: ORA-01476: 除数为 0
  • 生殖感染对生育的影响有哪些?劲松中西医结合医院专家详细解读
  • js模块化的应用!!!(前无古人,后无来者)
  • Photoshop Elements 2023 v21.0(ps简化版)
  • ambari 开启hdfs回收站机制
  • SpringDataRedis 操作 Redis,并指定数据序列化器
  • git 克隆无权限-重新输入账号密码
  • 文献阅读:基于改进ConvNext的玉米叶片病害分类
  • 计算机网络之网络传输,三次握手和四次挥手
  • 结构体精讲1
  • vscode插件离线下载
  • 国产智能运维操作系统新选择-浪潮KeyarchOS
  • DockerCompose修改某个服务的配置(添加或编辑端口号映射)后如何重启单个服务使其生效
  • Selenium 中并行测试的重要性!
  • java面试题-Hashmap、Hashtable、ConcurrentHashMap原理