C++(8) 运算符重载

文章目录

      • 运算符重载
          • 1.1 运算符概述
          • 1.2 运算符 + 重载
          • 1.3 运算符 << 重载

运算符重载

1.1 运算符概述

针对当前程序中常用的运算符,可以实现目标运算符处理当前数据类型的方式修改

需求:

"ABCD" + "BDC" ==> "ABCDBDC"
+ ==> 拼接函数
1.2 运算符 + 重载
#include 

#include 
#include 
#include 

using namespace std;

class MyString
{
public:
    MyString() {}
    MyString(char *str)
    {
        // strlen(str) 构造函数参数字符串长度
        size_t length = strlen(str);

        this->str = (char *)malloc(length + 1);
        memset(this->str, 0, length + 1);

        memcpy(this->str, str, length + 1);
    }

    MyString(const MyString &ms)
    {
        size_t length = strlen(ms.str);

        str = (char *)malloc(length + 1);
        memset(str, 0, length + 1);

        memcpy(str, ms.str, length + 1);
    }

    ~MyString()
    {
        free(str);
        str = NULL;
    }

    MyString *append(MyString *ms)
    {
        /*
        1. 计算当前字符串总长度
            strlen(str) 调用函数的字符串长度
            strlen(ms->str) 参数字符串长度
            相加之后当前字符串总长度
        */
        size_t length = strlen(str) + strlen(ms->str);

        // 2. 根据总长度申请的新的内存空间
        char *temp = (char *)malloc(length + 1);
        memset(temp, 0, length + 1);

        // 3. 将当前调用函数对象的 MyString 底层字符串数据拷贝到 temp 中
        memmove(temp, str, strlen(str));

        // 4. 将参数 MyString 对象底层字符串拼接到 temp 中
        strcat(temp, ms->str);

        // 5. 首先释放当前调用函数原本 str 内存空间
        free(str);

        // 6. 新申请的内存空间地址赋值给 str
        str = temp;

        return this;
    }

    /*
    opreator+
        + 运算符重载格式要求
            1. 必须有友元函数,类外开可以直接调用
            并且可以操作当前类内权限限制数据
            2. opreator+ 重载要求必须有两个参数,且必须使用引用类型
    */
    friend void operator+(MyString &m1, MyString &m2);

    char *getStr() { return str; }

private:
    char *str;
};

void operator+(MyString &m1, MyString &m2)
{
    /*
    ms1 对应 + 之前的内容
    ms2 对应 + 之后的内容
    */
    cout << "m1 : " << m1.str << endl;
    cout << "m2 : " << m2.str << endl;
    cout << "+ 运算符重载" << endl;

    // 1. 计算总长度
    size_t length = strlen(m1.str) + strlen(m2.str);

    // 2. 申请新空间
    char *temp = (char *)calloc(1, length + 1);

    // 3. m1 数据内容存储到新空间中
    memcpy(temp, m1.str, strlen(m1.str));

    // 4. m2 数据内容拼接到新空间中
    strcat(temp, m2.str);

    // 5. 释放 m1 原空间数据内容
    free(m1.str);

    // 6. m1 底层字符串存储新空间地址
    m1.str = temp;
}

int main(int argc, char const *argv[])
{
    MyString *ms1 = new MyString("ABC");
    MyString *ms2 = new MyString("1234");

    ms1 = ms1->append(ms2);

    /*
    MyString * operator+(MyString * m) 当前重载 + 运算符的函数是一个
    成员函数,需要通过 MyString 类型调用,但是 + 运算符属于基础运算符
    编译器在使用时,不会认为是【类型调用】

    编译器可以做的事情:
        1. + 运算符按照基本逻辑实现
        2. 如果发现基本逻辑无法满足执行要求,会检测到运算符两端的数据类型
        查询当前数据类型中是否存在对应的运算符的重载实现
    */
    MyString *ms3 = new MyString("!@$");
    *ms1 + *ms3;

    cout << ms1->getStr() << endl;

    delete ms2;
    delete ms1;

    return 0;
}
1.3 运算符 << 重载
#include 
#include 

using namespace std;

class Person
{
public:
    Person() {}
    Person(int id, string name, int age) : id(id), name(name), age(age) {}
    Person(const Person &p) : id(p.id), name(p.name), age(p.age) {}

    /*
    当前函数是重载了 << 运算符
        1. ostream & o 输出操作使用的 cout
        2. Person * p 目标展示的 Person 数据
        << 运算符重载替换的内容是 cout << p
        3. 返回值是 ostream & 输出流引用,方便连贯操作
    */
    friend ostream &operator<<(ostream &o, Person *p);

private:
    int id;
    string name;
    int age;
};

ostream &operator<<(ostream &o, Person *p)
{
    o << "ID : " << p->id << ", Name : " << p->name << ", Age : " << p->age;
    return o;
}

class Student
{
};

int main(int argc, char const *argv[])
{
    Person *p1 = new Person(1, "张三", 3);
    Person *p2 = new Person(2, "李四", 5);

    Student *s = new Student;

    /*
    当前使用的 << 运算符已经被 ostream 重载之后的运算符内容
    cout 就是 ostream 类型
        ostream Output Stream 输出流
    */
    cout << p1 << endl
         << p2 << " 字符串" << endl;
    /*
    执行结果:
        ID : 1, Name : 张三, Age : 3
        ID : 2, Name : 李四, Age : 5 字符串
    */

    cout << s << endl; // 0x903ca0

    return 0;
}

    cout << p1 << endl
         << p2 << " 字符串" << endl;
    /*
    执行结果:
        ID : 1, Name : 张三, Age : 3
        ID : 2, Name : 李四, Age : 5 字符串
    */

    cout << s << endl; // 0x903ca0

    return 0;
}

你可能感兴趣的:(c++,开发语言,c语言,学习,学习方法)