IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++杂讲 运算符重载 -> 正文阅读

[C++知识库]C++杂讲 运算符重载

目录

知识点1【运算符重载概述】

知识点2【可重载的运算符】

知识点3【运算符重载的步骤】

知识点4【重载运算符<<】

知识点5【重载>>运算符】

知识点6【重载==运算符】

知识点7【自增自减(++/--)运算符重载】

?知识点8【重载=赋值运算符】

?知识点9【重载 函数调用运算符 ()?】

知识点10【不要重载&& || 用户没办法实现短路特性?】(重要)

知识点11【不能重载的运算符】

知识点12【运算符重载案例】


知识点1【运算符重载概述】

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

比如:重载+运算符完成"lucy"+“bob”拼接

void operator+(参数1,参数2)
{
    
}

知识点2【可重载的运算符】

知识点3【运算符重载的步骤】

运算符重载分析步骤:

1、分析运算符左边的运算对象。如果不是自定义类的对象,只能用全局函数 实现运算符重载

????????全局函数的第一参数左边的运算对象

????????全局函数的第二个参数右边的运算对象

2、分析运算符左边的运算对象.如果是自定义类的对象,可以用全局函数、成员函数 实现运算符重载。

????????全局函数的第一参数左边的运算对象

????????全局函数的第二个参数右边对象

成员函数:可以省略一个参数,只需要将运算符右边的对象 传递到成员函数中。(推荐)

知识点4【重载运算符<<】

#include <iostream>
#include <string>
using namespace std;
class Person
{
    friend ostream& operator<<(ostream &out, Person &ob);
private:
    int num;
    string name;
    int age;
public:
    Person(){}
    Person(int num, string name, int age)
    {
        this->num = num;
        this->name = name;
        this->age = age;
    }
    void showPerson(void)
    {
        cout<<"学号:"<<num<<", 姓名:"<<name<<", 年龄:"<<age<<endl;
    }
};

//全局友元函数实现运算符重载
ostream& operator<<(ostream &out, Person &ob)
{
    out<<"学号:"<<ob.num<<", 姓名:"<<ob.name<<", 年龄:"<<ob.age<<endl;
    return out;
}

int main(int argc, char *argv[])
{
    Person ob1(100,"lucy", 18);
    Person ob2(101,"bob", 19);

    cout<<ob1<<ob2<<endl;// operator<<(cout,ob1);
    return 0;
}

知识点5【重载>>运算符】

#include <iostream>
#include <string>
using namespace std;
class Person
{
    friend ostream& operator<<(ostream &out, Person &ob);
    friend istream& operator>>(istream &in, Person &ob);
private:
    int num;
    string name;
    int age;
public:
    Person(){}
    Person(int num, string name, int age)
    {
        this->num = num;
        this->name = name;
        this->age = age;
    }
    void showPerson(void)
    {
        cout<<"学号:"<<num<<", 姓名:"<<name<<", 年龄:"<<age<<endl;
    }
};

//全局友元函数实现运算符重载
ostream& operator<<(ostream &out, Person &ob)
{
    out<<"学号:"<<ob.num<<", 姓名:"<<ob.name<<", 年龄:"<<ob.age<<endl;
    return out;
}

//全局友元函数实现运算符重载
istream& operator>>(istream &in, Person &ob)
{
    in>>ob.num>>ob.name>>ob.age;
    return in;
}

int main(int argc, char *argv[])
{
    Person ob1(100,"lucy", 18);
    Person ob2(101,"bob", 19);

    cout<<ob1<<ob2<<endl;// operator<<(cout,ob1);

    Person ob3;
    cin>>ob3;
    cout<<ob3;
    return 0;
}

知识点6【重载==运算符】

#include <iostream>
#include <string>
using namespace std;
class Person
{
    friend ostream& operator<<(ostream &out, Person &ob);
    friend istream& operator>>(istream &in, Person &ob);
    //friend bool operator==(Person &ob1, Person &ob2);
private:
    int num;
    string name;
    int age;
public:
    Person(){}
    Person(int num, string name, int age)
    {
        this->num = num;
        this->name = name;
        this->age = age;
    }
    void showPerson(void)
    {
        cout<<"学号:"<<num<<", 姓名:"<<name<<", 年龄:"<<age<<endl;
    }

    //成员函数完成==重载
    bool operator==(Person &ob)
    {
        if(num==ob.num && name==ob.name && age==ob.age)
            return true;
        else
            return false;
    }

};

//全局友元函数实现运算符重载
ostream& operator<<(ostream &out, Person &ob)
{
    out<<"学号:"<<ob.num<<", 姓名:"<<ob.name<<", 年龄:"<<ob.age<<endl;
    return out;
}

//全局友元函数实现运算符重载
istream& operator>>(istream &in, Person &ob)
{
    in>>ob.num>>ob.name>>ob.age;
    return in;
}

#if 0
//全局友元函数 实现==重载
bool operator==(Person &ob1, Person &ob2)
{
    if(ob1.num==ob2.num && ob1.name==ob2.name && ob1.age==ob2.age)
        return true;
    else
        return false;
}
#endif

int main(int argc, char *argv[])
{
    Person ob1(100,"lucy", 18);
    Person ob2(101,"bob", 19);

    cout<<ob1<<ob2<<endl;// operator<<(cout,ob1);

    Person ob3;
    cin>>ob3;
    cout<<ob3;

    //ob1.operator==(ob2);
    if(ob1 == ob2)
    {
        cout<<"相等"<<endl;
    }
    else
    {
        cout<<"不相等"<<endl;
    }
    return 0;
}

知识点7【自增自减(++/--)运算符重载】

当编译器看到 ++a? ?(前置++),它就调用operator++(a),

当编译器看到 a++? ?(后置++),它就会去调用operator++(a,int)

全局函数实现:

????????++ob ------------->operator++(ob)

????????ob++ ------------->operator++(ob, int)

成员函数实现:

????????++ob ------------->ob.operator++()

????????ob++ ------------->ob.operator++(int)

#include <iostream>

using namespace std;
class Data
{
    friend ostream& operator<<(ostream &out, Data ob);
private:
    int a;
    int b;
public:
    Data(){}
    Data(int a, int b):a(a),b(b){}

    //重载ob++  先使用  后加减
    Data operator++(int)
    {
        //保存++之前的值
        Data tmp = *this;

        //进行自增
        a = a+1;
        b = b+1;

        return tmp;//返回++之前的值
    }

    //重载++ob  先加减  后使用
    Data operator++()
    {
        //先加减
        a=a+1;
        b=b+1;

        //再使用
        return *this;
    }

};
ostream& operator<<(ostream &out, Data ob)
{
    out<<"a="<<ob.a<<", b="<<ob.b<<endl;
    return out;
}

int main(int argc, char *argv[])
{
    Data ob1(10,20);
    cout<<ob1<<endl;
    cout<<ob1++<<endl;
    cout<<ob1<<endl;

    Data ob2(100,200);
    cout<<ob2<<endl;
    cout<<++ob2<<endl;
    cout<<ob2<<endl;
    return 0;
}

?知识点8【重载=赋值运算符】

(类中有指针成员 才需要重载=)

如果类中没有指针成员 相同类型的对象 可以直接=赋值(浅拷贝)

如果类中有指针成员 相同类型的对象 必须重载=(深拷贝)

#include<string.h>
class Data2
{
public:
    char *str;//指针成员
public:
    Data2(){}
    Data2(char *str)
    {
        this->str = new char[strlen(str)+1];
        strcpy(this->str, str);
    }
    ~Data2()
    {
        if(str != NULL)
        {
            delete [] str;
            str=NULL;
        }
    }
    //重载=
    Data2& operator=(Data2 &ob)
    {
        cout<<"重载="<<endl;
        this->str = new char[strlen(ob.str)+1];
        strcpy(this->str, ob.str);
        return *this;
    }
};
void test02()
{
    Data2 ob1("hello world");
    Data2 ob2;
    Data2 ob3;
    ob3 = ob2 = ob1;
    cout<<ob2.str<<endl;
    cout<<ob3.str<<endl;
}

总结:如果类中有指针成员

必须实现拷贝构造(深拷贝)、必须实现析够函数(释放指针成员所指向的空间)、必须重载=运算符(深拷贝)

?知识点9【重载 函数调用运算符 ()?】

class Print
{
public:
    void operator()(char *str)
    {
        cout<<str<<endl;
    }
};
void test03()
{
    Print ob;
    ob.operator ()("hello world");

    //仿函数(本质 不是函数  只是像函数调用)
    //对象名 与 ()结合   触发了operator()调用   (本质)
    ob("hello beijing");

    //Print()是Print类的匿名对象
    Print()("hello qf");
}

8、不要重载&& || 用户没办法实现短路特性 (重要)

知识点10【不要重载&& || 用户没办法实现短路特性?】(重要)

知识点11【不能重载的运算符】

?

知识点12【运算符重载案例】

mystring.h

#ifndef MYSTRING_H
#define MYSTRING_H
#include<iostream>
using namespace std;

class MyString
{
    friend ostream& operator<<(ostream &out, MyString ob);
private:
    char *str;
    int size;
public:
    MyString();
    MyString(char *str);
    MyString(const MyString &ob);
    ~MyString();

    //获取字符串的长度
    int getSize(void);
    //获取字符
    char& operator[](int pos);
    char& at(int pos);

    //重载赋值运算符=
    MyString& operator=(MyString &ob);
    MyString& operator=(char *str);

    //重载赋值运算符+=
    MyString& operator+=(MyString &ob);
    MyString& operator+=(char *str);

    //重载+运算符
    MyString operator+(MyString &ob);
   // MyString operator+(char *str);

    bool operator>(MyString &ob);

};


#endif // MYSTRING_H

myString.cpp

#include "mystring.h"
#include<string.h>
#include<iostream>
using namespace std;
MyString::MyString()
{
    str=NULL;
    size=0;
    cout<<"无参构造"<<endl;
}

MyString::MyString(char *str)
{
    size = strlen(str);
    this->str = new char[size+1];
    strcpy(this->str, str);
    cout<<"有参构造"<<endl;
}

MyString::MyString(const MyString &ob)
{
   size = ob.size;
   str = new char[size +1];
   strcpy(str, ob.str);
   cout<<"拷贝构造函数"<<endl;
}

MyString::~MyString()
{
    if(str != NULL)
    {
        delete [] str;
        str = NULL;
    }
    cout<<"析够函数调用"<<endl;
}

int MyString::getSize()
{
    return size;
}

char& MyString::operator[](int pos)
{
    if(pos>=0 && pos<size)
    {
        return str[pos];
    }
    else
    {
        cout<<"坐标无效"<<endl;
    }
}

char &MyString::at(int pos)
{
    if(pos>=0 && pos<size)
    {
        return str[pos];
    }
    else
    {
        cout<<"坐标无效"<<endl;
    }
}

MyString &MyString::operator=(MyString &ob)
{
    //ob1 = ob
    //先释放ob1.str指向的堆区空间
    if(str != NULL)
    {
        delete [] str;
        str=NULL;
    }

    size = ob.size;
    str = new char[size+1];
    strcpy(str, ob.str);

    return *this;
}

MyString &MyString::operator=(char *str)
{
    //先释放ob1.str指向的堆区空间
    if(this->str != NULL)
    {
        delete [] this->str;
        this->str=NULL;
    }

    size = strlen(str);
    this->str = new char[size+1];
    strcpy(this->str, str);

    return *this;
}

MyString& MyString::operator+=(MyString &ob)
{
    if((str==NULL) && (ob.str != NULL))
    {
        size = ob.size;
        str = new char[size+1];
        memset(str, 0,size+1);
        strcpy(str, ob.str);

        //记得返回
    }
    else if((str != NULL) && (ob.str == NULL))
    {
        //记得返回
    }
    else if((str == NULL) && (ob.str == NULL))
    {
        cout<<"全为NULL无法拼接"<<endl;
        //记得返回
    }
    else if((str != NULL) && (ob.str != NULL))
    {
        //str7 += str8
        //新空间的大小
        size = size+ob.size;
        char *tmp_str = new char[size+1];
        //清空新空间的内容
        memset(tmp_str, 0, size+1);

        strcpy(tmp_str, str);
        strcat(tmp_str, ob.str);

        //释放str指向的空间
        delete [] str;
        str = tmp_str;
        //记得返回
    }

    return *this;
}

MyString &MyString::operator+=(char *str)
{
    if(this->str == NULL)
    {
        size = strlen(str);
        this->str = new char[size+1];
        memset(this->str, 0, size+1);
        strcpy(this->str, str);
    }
    else if(this->str != NULL)
    {
        size = size+strlen(str);
        char *tmp_str = new char[size+1];
        memset(tmp_str, 0, size+1);
        strcpy(tmp_str, this->str);
        strcat(tmp_str, str);

        //释放this->str指向的旧空间
        delete [] this->str;
        this->str = tmp_str;
    }
    return *this;
}

MyString MyString::operator+(MyString &ob)
{
    if((this->str==NULL) && (ob.str == NULL))
    {
        cout<<"全空无法进行+运算"<<endl;
        return *this;
    }
    else if((this->str!=NULL) && (ob.str == NULL))
    {
        return *this;
    }
    else if((this->str==NULL) && (ob.str != NULL))
    {
        return ob;
    }
    else if((this->str!=NULL) && (ob.str != NULL))
    {
        char *buf=new char[size+ob.size+1];
        memset(buf, 0, size+ob.size+1);
        strcpy(buf,this->str);
        strcat(buf, ob.str);

        MyString tmp(buf);

        delete [] buf;

        return tmp;
    }
}

bool MyString::operator>(MyString &ob)
{
    if((str != NULL) && (ob.str != NULL) )
    {
        if(strcmp(str, ob.str)>0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        cout<<"存在NULL字符串无法比较大小"<<endl;
    }
    return false;
}

//全局函数重载<<运算符
ostream& operator<<(ostream &out, MyString ob)
{
    cout<<ob.str;
    return out;
}

main.cpp

#include <iostream>
#include "mystring.h"
using namespace std;

int main(int argc, char *argv[])
{
#if 0
    MyString str1("hello");
    cout<<"str1的长度="<<str1.getSize()<<endl;
    cout<<str1<<endl;

    //获取str1的某个字符
    str1[2] = 'W';
    cout<<str1[2] <<endl;
    str1.at(3)='H';
    cout<<str1<<endl;

    //对象赋值
    MyString str2("hello");
    MyString str3("world");
    MyString str4("hehe");
    str4 = str3 = str2;
    cout<<str4<<endl;

    //字符串 给对象赋值
    MyString str5;
    MyString str6;

    str6 = str5 = "hello";
    cout<<str6<<endl;

    MyString str7("hello");
    MyString str8("world");

    str7 += str8;
    cout<<str7<<endl;

    MyString str9;

    str9+="world";
    cout<<str9<<endl;
#endif
    MyString str10("hello");
    MyString str11("world");
    MyString str12("hehe");


    cout<<(str10+str11+str12)<<endl;

    if(str11 > str12)
    {
        cout<<"大于"<<endl;
    }
    else
    {
        cout<<"不大于"<<endl;
    }

    return 0;
}

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-06 17:10:30  更:2022-06-06 17:10:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/11 6:06:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码