• 玩转C++运算符重载


    运算符重载语法:返回值类型  operator运算符(参数列表) {  代码逻辑。。。 }

    C++中的运算符重载是通过函数来实现的,可以将重载的运算符看作是类成的一个成员函数,向普通函数一样调用。如重载String类的 + 运算符,调用的时候可以这样:

    class {
       // .....
       String operator+(const String &str)
       { .... }
    }
    
    String str1 = "hello ";
    String str2 = "cplusplus";
    String str3 = str1.operator+(str2);
            从上述代码中可以看出,operator+就像是String类的一个函数,可以像普通函数一样调用,将要相加的字符串对象作为实参传递给函数即可。所以从这可以得出一个函数重载的步聚:(以上述+重载为例)

    1、写出运算符的函数原型

    str1.operator+(str2); 

    从这可以得知,+ 需要两个操作数,str1和str2(即两个字符串对象),返回值类型为String对象(加法运算后的结果)。由于是作为类的成员函数重载,所以str1在进行 + 运算时作为this指针传给函数,函数只需要一个参数即可,即被相加的字符串对象str2。

    2、写出函数声明

    从函数原型可以得出函数声明:String operator+(const String &str);

    3、实现函数细节

    String String::operator+(const String &str)
    {
        if (str.buff == nullptr)
        {
            return *this;
        }
        
        size_t totallen = str.len + this->len + 1;
        char *buff = new char[totallen];
        
        strcpy(buff, this->buff);
        strcat(buff, str.buff);
        
        String temp(buff);
        return temp;
    }

    下面这个示例重载了字符串操作的常用操作符:

    //
    //  String.h
    //  C++运算符重载
    //
    //  Created by 杨信 on 14-5-8.
    //  Copyright (c) 2014年 yangxin. All rights reserved.
    //
    
    #ifndef __C______String__
    #define __C______String__
    
    #include <iostream>
    
    using namespace std;
    
    class String
    {
    private:
        char *buff;
        size_t len;
        
    public:
        String();
        
        // 用一个字符串初始化对象
        String(const char *buff);
        
        // 拷贝构造
        String(const String &str);
        
        // 析构
        ~String();
        
        // 设置字符串内容
        void setString(const char *buff);
        
        // 获取字符串的长度
        size_t length() const;
        
        // 获取字符串内容
        char * getStr() const;
        
        // 比较两个字符串是否相等
        bool operator==(String &str);
        
        // 比较两个字符串是否不相等
        bool operator!=(String &str);
        
        // 比较两个字符串的大小
        bool operator>(String &str);
        
        // 比较两个字符串的大小
        bool operator<(String &str);
        
        // 获取或修改字符串中的某一个字符
        char& operator[](int index);
        
        // 赋值构造函数
        String& operator=(const String &str);
        
        // 两个字符串相加
        String operator+(const String &str);
        
        // 字符串累加
        String& operator+=(const String &str);
        
        // 从输入流中获取字符串
        friend istream& operator>>(istream &input, String &str);
        
        // 将字符串输出到输出流
        friend ostream& operator<<(ostream &output, const String &str);
        
    };
    
    #endif /* defined(__C______String__) */
    
    //
    //  String.cpp
    //  C++运算符重载
    //
    //  Created by 杨信 on 14-5-8.
    //  Copyright (c) 2014年 yangxin. All rights reserved.
    //
    
    #include "String.h"
    #include <string>
    #include <cassert>
    #include <cmath>
    
    String::String()
    {
        this->buff = nullptr;
        this->len = 0;
    }
    
    // 用一个字符串初始化对象
    String::String(const char *buff):buff(nullptr), len(0)
    {
        setString(buff);
    }
    
    // 拷贝构造
    String::String(const String &str)
    {
        setString(str.buff);
    }
    
    // 析构
    String::~String()
    {
        // 释放内存
        if (this->buff != nullptr)
        {
            delete[] buff;
            buff = nullptr;
            len = 0;
        }
    }
    
    void String::setString(const char *buff)
    {
        if (buff == nullptr)
        {
            return;
        }
        
        if (this->buff != nullptr) {
            delete[] this->buff;
            this->buff = nullptr;
            this->len = 0;
        }
        
        size_t len = strlen(buff);
        this->buff = new char[len + 1];
        this->len = len;
        strcpy(this->buff, buff);
    }
    
    // 获取字符串的长度
    size_t String::length() const
    {
        return this->len;
    }
    
    // 获取字符串内容
    char * String::getStr() const
    {
        return this->buff;
    }
    
    // 获取或修改字符串中的某一个字符
    char& String::operator[](int index)
    {
        assert(index < this->len);
        
        return this->buff[index];
    }
    
    // 比较两个字符串是否相等
    bool String::operator==(String &str)
    {
        if (this->len != str.len)
        {
            return false;
        }
        
        for (int i = 0; i < this->len; ++i)
        {
            if (this->buff[i] != str[i])
            {
                return false;
            }
        }
        
        return true;
    }
    
    // 比较两个字符串是否不相等
    bool String::operator!=(String &str)
    {
        return !(*this == str);
    }
    
    // 比较两个字符串的大小
    bool String::operator>(String &str)
    {
        char *pstr = this->buff;
        char *pstr2 = str.buff;
        while (*pstr != '' && *pstr2 != '')
        {
            if (*pstr > *pstr2) {
                return true;
            }
            pstr++;
            pstr2++;
        }
        return false;
    }
    
    // 比较两个字符串的大小
    bool String::operator<(String &str)
    {
        return !(*this > str);
    }
    
    // 赋值构造函数
    String& String::operator=(const String &str)
    {
        setString(str.buff);
        
        return *this;
    }
    
    // 两个字符串相加
    String String::operator+(const String &str)
    {
        if (str.buff == nullptr)
        {
            return *this;
        }
        
        size_t totallen = str.len + this->len + 1;
        char *buff = new char[totallen];
        
        strcpy(buff, this->buff);
        strcat(buff, str.buff);
        
        String temp(buff);
        return temp;
    }
    
    // 字符串累加
    String& String::operator+=(const String &str)
    {
        if (str.buff == nullptr)
        {
            return *this;
        }
        
        // 创建一个临时缓冲区,存储对象本身的字符串和相加的字符串
        size_t len = this->len + str.length();
        char *temp = new char[len + 1];
        strcpy(temp, this->buff);
        strcat(temp, str.buff);
        
        // 设置新的字符串给对象本身
        setString(temp);
        
        return *this;
    }
    
    // 从输入流中获取字符串
    istream& operator>>(istream &input, String &str)
    {
        // 在堆区创建临时缓冲区,接收用户输入
        int size = 1024 * 10;
        char *tempbuff = new char[size];
        memset(tempbuff, 0, size);
        
        // 获取用户输入
        input.getline(tempbuff, size);
        
        // 将临时缓冲中的字符串保存到str对象的字符串缓冲区中
        str.setString(tempbuff);
        
        // 释放临时缓冲区数据
        delete[] tempbuff;
        tempbuff = nullptr;
        return input;
    }
    
    // 将字符串输出到输出流
    ostream& operator<<(ostream &output, const String &str)
    {
        output << str.getStr();
        return output;
    }
    
    // 测试用例
    //
    //  main.cpp
    //  String(运算符重载)
    //
    //  Created by 杨信 on 14-5-8.
    //  Copyright (c) 2014年 yangxin. All rights reserved.
    //
    
    #include <iostream>
    #include "String.h"
    #include <cmath>
    
    using namespace std;
    
    
    int main(int argc, const char * argv[])
    {
       
        // 初始化
        String str1("helloz");
        String str2("helloz");
        
        // 获取字符中内容
        cout << str1.getStr() << endl;
        
        // 获取字符串的长度
        cout << "长度:" << str1.length() << endl;
        
        // 获取第字符串中的第一个字符
        cout << "第1个字符:" << str1[0] << endl;
        
        // 比较两个字符串是否相等,相等返回1,否则返回0
        bool isequal = str1 == str2;
        cout << isequal << endl;
        
        // 比较两个字符串的大小,str1大于str2返回1,否则返回0
        cout << (str1 > str2) << endl;
        
        // 修改字符串中的第2个字符为C
        String s = "Hello";
        s[1] = 'C';
        cout << s << endl;
        
        // 测试用一个字符串去初始化另外一个字符串
        String str3 = str2;
        cout << str3.getStr() << endl;
        String str4;
        str4 = str3;
        cout << str4.getStr() << endl;
        
        // 测试两个字符串相加
        String str5 = str1 + str2;
        cout << &str5 << endl;
        cout << str5.getStr() << endl;
        
        // 测试字符串连等
        String str6;
        String str7 = str6 = str5;
        cout << str6.getStr() << " | " << str7.getStr() << endl;
        
        // 测试字符串累加
        String str8 = "i love c++ ";
        str8 += "i love c ";
        cout << str8.getStr() << endl;
        
        // 从输入流读取字符串
        String str9;
        cout << "Please a string:";
        cin >> str9;
        
        // 将字符串输出到输出流
        cout << str9 << endl;
       
        return 0;
    }
    运算符重载注意事项:

    • 友元函数重载运算符时需要传递所有操作数
    • 成员函数重载,会将操作数本身做为this指针作为参数传入函数,如果是多元操作符,只需与它被操作的数传入函数即可
    • = 号重载时,如果对象中有新分配内存的成员,要先delete,再new,如果要支持连等操作,需要返回对象本身的引用

    • 函数返回值作左值时,返回值必须为引用

    • 只有C++预定义的操作符集中的操作符才可以被重载(不能自己随便写一个操作符,如:+-)
    • 重载操作符不能改变操作符的优先级,例如:先乘徐,后加减
    • 重载操作符不能改变操作数的个数

    以下几种运算符不能被重载:

    •  .    :成员选择运算符
    • ::    :作用域运算符
    • *     : 指针运算符
    • #    :预处理标志
    • ?:   :三目运算符,没有确定性,重载没有意义


  • 相关阅读:
    http-proxy-middleware与express.json()的bug
    20+前端常用的vscode插件(总结推荐)
    图解翻转单向链表,超详细(python语言实现)
    pytest + allure2.x 踩坑-报告无数据
    Pycharm+pytest+allure打造高逼格的测试报告
    Appium Appium Python API 中文版
    appium模拟键盘事件
    AppiumDesktop控制手机和安卓模拟器
    Appium环境搭建超详细教程
    Fiddler抓包工具总结
  • 原文地址:https://www.cnblogs.com/xyang0917/p/4172503.html
Copyright © 2020-2023  润新知