C++学习笔记“类和对象”;运算符重载

目录

[4.5 运算符重载](#4.5 运算符重载)

[4.5.1 加号运算符重载](#4.5.1 加号运算符重载)

[4.5.2 左移运算符重载](#4.5.2 左移运算符重载)

[4.5.3 递增运算符重载](#4.5.3 递增运算符重载)

[4.5.4 赋值运算符重载](#4.5.4 赋值运算符重载)

[4.5.5 关系运算符重载](#4.5.5 关系运算符重载)

[4.5.6 函数调用运算符重载](#4.5.6 函数调用运算符重载)


4.5 运算符重载

运算符重载概念:

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

4.5.1 加号运算符重载

作用:实现两个自定义数据类型相加的运算

cpp 复制代码
#include <iostream>
using namespace std;

// 加号运算符重载

class Person {
    public:
        //1、成员函数重载+号
        // Person operator+( Person& p) {
        //     Person temp;
        //     temp.m_A = m_A + p.m_A;
        //     temp.m_B = m_B + p.m_B;
        //     return temp;
        // }

        int m_A;
        int m_B;
};

//2、全局函数重载+号
Person operator+( Person& p1, Person& p2) {
    Person temp;
    temp.m_A = p1.m_A + p2.m_A;
    temp.m_B = p1.m_B + p2.m_B;
    return temp;
}

// 函数重载的版本
Person operator+( Person& p1, int num) {
    Person temp;
    temp.m_A = p1.m_A + num;
    temp.m_B = p1.m_B + num;
    return temp;
}

void test_1(){
    Person p1, p2;
    p1.m_A = 10;
    p1.m_B = 20;
    p2.m_A = 30;
    p2.m_B = 40;

    // 成员函数重载本质调用
    // Person p3 = p1.operator+(p2);

    // 全局函数重载本质调用
    // Person p3 = operator+(p1, p2);

    Person p3 = p1 + p2;
    cout << "p3.m_A = " << p3.m_A << endl;
    cout << "p3.m_B = " << p3.m_B << endl;

    // 运算符重载,也可以发生函数重载
    Person p4 = p1 + 100;
    cout << "p4.m_A = " << p4.m_A << endl;
    cout << "p4.m_B = " << p4.m_B << endl;
}

int main() {
    test_1();
    return 0;
}

总结1:对于内置的数据类型的表达式的的运算符是不可能改变的

总结2:不要滥用运算符重载

4.5.2 左移运算符重载

作用:可以输出自定义数据类型

cpp 复制代码
#include <iostream>
using namespace std;

// 左移运算符重载
class Person {
	friend ostream& operator<<(ostream& cout,  Person& p);
public:
	Person(int a, int b) {
		m_A = a;
		m_B = b;
	}
private:
	int m_A;
	int m_B;
};

// 只能利用全局函数进行 左移运算符重载
ostream& operator<<(ostream& cout, Person& p) {
	cout << "A: " << p.m_A << " B: " << p.m_B << endl;
	return cout;
}

void test() {
	Person p(10, 20);
	cout << p << endl;
}

int main() {
	test();

	system("pause");
	return 0;
}

总结:重载左移运算符配合友元可以实现输出自定义数据类型

4.5.3 递增运算符重载

作用:通过重载递增运算符,实现自己的整型数据

cpp 复制代码
#include <iostream>
using namespace std;

// 递增运算符重载

// 自定义类
class MyInteger {
    friend ostream& operator<<(ostream& os, MyInteger& myInt);
private:
    int m_Num;
public:
    MyInteger() {m_Num = 10;}
    // 前置递增运算符重载
    MyInteger& operator++() {
        m_Num++;// 先自增,再返回引用
        return *this;// 返回引用,以便可以连续使用++
    }
    // 后置递增运算符重载
    MyInteger operator++(int) { // int代表占位参数用于区分前置和后置
        MyInteger temp = *this;// 先拷贝一份副本,记录原值
        m_Num++;// 后递增
        return temp;// 返回临时对象,以便可以连续使用++
    }
};

// 重载<<运算符
ostream& operator<<(ostream& os,  MyInteger& myInt) {
    os << "MyInteger: " << myInt.m_Num;
    return os;
}
// 前置递增运算符重载测试
void test1() {
    MyInteger myInt;
    cout << "前置Before ++: " << ++myInt << endl;
    cout << "前置After ++: " << myInt << endl;
}

// 后置递增运算符重载测试
void test2() {
    MyInteger myInt;
    cout << "Before ++: " << myInt++ << endl;
    cout << "After ++: " << myInt << endl;
}

int main() {
    test1();
    test2();

    system("pause");
    return 0;
}

总结:前置递增返回引用,后置递增返回值

4.5.4 赋值运算符重载

C++编译器至少给一个类添加4个函数

  • 1.默认构造函数(无参,函数体为空)
  • 2.默认析构函数(无参,函数体为空)
  • 3.默认拷贝构造函数,对属性进行值拷贝
  • 4.赋值运算符 operator=,对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

示例:

cpp 复制代码
#include <iostream>
using namespace std;

// 赋值运算符重载

class Person {
    friend void test();// 声明test函数的友元
public:
    Person(int age) {
        m_Age = new int(age);
    }
    ~Person() {
        if (m_Age != nullptr) {
            delete m_Age;
            m_Age = nullptr;
        }
    }

    // 赋值运算符重载
    Person& operator=(const Person& p) {//const修饰符表示p是常量引用,不能修改p的值;
        //编译器默认提供的赋值运算符是浅拷贝,即只拷贝指针,不会拷贝堆区的数据
        //因此需要手动实现深拷贝
        //m_Age = p.m_Age; // 直接赋值指针,不会拷贝堆区的数据

        // 先判断是否有属性在堆区,如果有,先释放掉,再深拷贝
        if (m_Age != NULL) {
            delete m_Age;
            m_Age = NULL;
        }
        m_Age = new int(*p.m_Age); // 利用指针的赋值运算符重载;深拷贝
        return *this;// 返回对象本身
    }
private:
    int *m_Age;// 指向整数的指针
};

void test() {
    Person p1(20);
    Person p2(30);
    Person p3(40);
    p3 = p2 = p1; // 调用赋值运算符重载;赋值操作
    cout << "p1 age: " << *p1.m_Age << endl;
    cout << "p2 age: " << *p2.m_Age << endl;
    cout << "p3 age: " << *p3.m_Age << endl;
}

int main() {
    test();

    system("pause");
    return 0;
}
4.5.5 关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 重载关系运算符

class Person {
	public:
		Person(string name, int age) {
			m_Name = name;
			m_Age = age;
		}
		// 重载关系运算符
		bool operator==(const Person& p) const {
			return m_Name == p.m_Name && m_Age == p.m_Age;// 这里的 && 代表两个条件都满足才返回 true
		}
		bool operator!=(const Person& p) const {
			return m_Name!= p.m_Name || m_Age != p.m_Age;// 这里的 || 代表两个条件有一个满足就返回 true
		}
		bool operator<(const Person& p) const {
			return m_Age < p.m_Age;// 这里的 < 代表 p1.m_Age < p2.m_Age
		}
		bool operator>(const Person& p) const {
			return m_Age > p.m_Age;// 这里的 > 代表 p1.m_Age > p2.m_Age
		}
	
		string m_Name;
		int m_Age;
};
void test() {
	Person p1("Tom", 20);
	Person p2("Jerry", 25);
	if (p1 == p2) {
		cout << "p1 == p2" << endl;
	}
	if (p1!= p2) {
		cout << "p1!= p2" << endl;
	}
	if (p1 < p2) {
		cout << "p1 < p2" << endl;
	}
	if (p1 > p2) {
		cout << "p1 > p2" << endl;
	}
	
}

int main() {
	test();
	return 0;
}
4.5.6 函数调用运算符重载
  • 函教调用运算符()也可以重载
  • 由于重载后使用的方式非常像函数的调用,因此称为仿函数
  • 仿函数没有固定写法,非常灵活

示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 函数调用运算符重载

// 打印输出类
class Printer {
public:
    // 重载函数调用运算符
    void operator()(string text) {
        cout << text << endl;
    }
    
};
void Printer_test(string text) {
    cout << text << endl;
}

void test() {
    Printer p;
    p("Hello, world!");// 由于使用起来类似于函数调用,因此也称为 仿函数

    Printer_test("Hello, world!");// 调用普通函数
}

// 仿函数非常灵活,没有固定写法
// 加法类
class Adder {
public:
    int operator()(int a, int b) {
        return a + b;
    }
};
void test2() {
    Adder a;
    int result = a(10, 20);
    cout << result << endl;

    // 匿名函数对象
    cout << "匿名函数对象: 10 + 20 = " << Adder()(10, 20) << endl;//
}

int main() {
    test();
    test2();

    system("pause");
    return 0;
}
相关推荐
PandaCave16 分钟前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
萝卜兽编程20 分钟前
优先级队列
c++·算法
yuwinter21 分钟前
鸿蒙HarmonyOS学习笔记(2)
笔记·学习·harmonyos
red_redemption43 分钟前
自由学习记录(23)
学习·unity·lua·ab包
幽兰的天空1 小时前
默语博主的推荐:探索技术世界的旅程
学习·程序人生·生活·美食·交友·美女·帅哥
游走于计算机中摆烂的1 小时前
启动前后端分离项目笔记
java·vue.js·笔记
珹洺2 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
孙同学要努力2 小时前
C++知识整理day1——前置基础知识整理(命名空间、输入输出、函数重载、引用)
开发语言·c++
沐泽Mu2 小时前
嵌入式学习-C嘎嘎-Day05
开发语言·c++·学习
几窗花鸢2 小时前
力扣面试经典 150(下)
数据结构·c++·算法·leetcode