C++ 运算符重载(八)

发布于:2023-01-04 ⋅ 阅读:(352) ⋅ 点赞:(0)

运算符重载的概念

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

2.运算符重载的目的是让语法更加简洁

3.运算符重载不能改变本来寓意,不能改变基础类型寓意

4.运算符重载的本质是另一种函数调用(是编译器去调用)

5.这个函数同一的名字叫operator

6.重载函数可以写成全局或成员函数

7.重载函数如果写成全局的,那么双目运算符左边的是第一个参数,右边是第二个参数

8.重载函数如果写成成员函数,那么双目运算符的左边是this,右边是第一个参数

9.不能改变运算符优先级,不能改变运算符的参数个数。

1.加号运算符重载

1.同类型的对象相加

class Maker
{
public:
    Maker(int id, int age)
    {
        this->id = id;
        this->age = age;
    }
    //写成成员函数,那么只需要一个参数,这个参数是加号的右边
    Maker operator+(Maker &m2)
    {
        Maker temp(this->id + m2.id, this->age + m2.age);
​
        return temp;
    }
public:
    int id;
    int age;
};
​
//全局方式 //3.编译器调用这个函数
//Maker operator+(Maker &p1,Maker &p2)//2.编译器检查参数是否对应,第一个参数是加的左边,第二参数是加号的右边
//{
//  Maker temp(p1.id + p2.id, p1.age + p2.age);
//
//  return temp;
//}
​
void test01()
{
    Maker m1(1, 20);
    Maker m2(2, 22);
    //+也叫双目运算符
    Maker m3=m1 + m2;//1.编译器看到两个对象相加,那么编译器会去找有没有叫operator+的函数
​
    cout << "id:" << m3.id << " age:" << m3.age << endl;
​
    //复数加
    Maker m4 = m1 + m2 + m3;
    cout << "id:" << m4.id << " age:" << m4.age << endl;
}

2.不同类型的对象相加

class Maker
{
public:
    Maker(int id, int age)
    {
        this->id = id;
        this->age = age;
    }
    
public:
    int id;
    int age;
};
class Student
{
public:
    Student()
    {
        mid = 0;
    }
    Student(int id)
    {
        mid = id;
    }
public:
    int mid;
};
​
Student operator+(Maker &m, Student &s)
{
    Student tmp(m.id + s.mid);
​
    return tmp;
    
}
​
Student operator+(Student &s, Maker &m)
{
    Student tmp(m.id + s.mid);
​
    return tmp;
​
}
​
void test()
{
    Maker m1(1, 18);
    Student s1(2);
    Student s2 = m1 + s1;
​
    s1 + m1;
}

2.减号运算符重载

class Maker
{
public:
    Maker(int id)
    {
        this->id = id;
    }
    Maker operator-(Maker &m2)
    {
        Maker tmp(this->id - m2.id);
        return tmp;
    }
public:
    int id;
};
​
int operator-(Maker &m,int b)
{
    return m.id-b;
}
​
void test()
{
    Maker m1(10);
    Maker m2(5);
    Maker m3 = m1 - m2;
    cout << m3.id << endl;
​
    int a = m3 - 5;
    cout << a << endl;
}

3.左移和右移运算符重载

1.左移运算符重载

1.cout是对象,<<是左移运算符

2.重载左移运算符是为了直接打印对象

3.形参和实参是一个对象

4.不能改变库类中的代码

5.ostream中把拷贝构造函数私有化了

4.如果要和endl一起使用,那么必须返回ostream的对象.

class Maker
{
    //如果要访问类的私有成员,那么把<<重载函数声明为友元
    friend ostream& operator<<(ostream &out, Maker &m);
public:
    Maker(int id,string name)
    {
        this->id = id;
        this->name = name;
    }
​
private:
    int id;
    string name;
};
//1.形参和实参是一个对象
//2.不能改变库类中的代码
//3.ostream中把拷贝构造函数私有化了
//4.如果要和endl一起使用,那么必须返回ostream的对象
ostream& operator<<(ostream &out, Maker &m)
{
    cout << m.id <<" "<<m.name<< endl;
​
    return out;
}
​
void test01()
{
    Maker m(10,"小花");
    cout << m << endl;
    cout << endl;
    /*
    endl是一个函数
    operator<<(endl)
    */
​
    cout << 10;//内部重载了基础数据类型
}

2.右移运算符重载

class Maker
{
    friend istream & operator>>(istream &in, Maker &m);
public:
    Maker(string name, int age)
    {
        this->name = name;
        this->age = age;
    }
    int getAge()
    {
        return age;
    }
private:
    string name;
    int age;
};
​
istream &operator>>(istream &in, Maker &m)
{
    in >> m.age;
    in >> m.name;
​
    return in;
}
​
void test02()
{
    Maker m("悟空", 15);
    Maker m2("悟空2", 25);
​
    cin >> m>>m2;
​
    cout << m.getAge() << endl;
    cout << m2.getAge() << endl;
​
}

4.赋值运算符重载

1.编译器默认给类提供了一个默认的赋值运算符重载函数

2.默认的赋值运算符重载函数进行了简单的赋值操作

class Maker
{
public:
    Maker()
    {
        id = 0;
        age = 0;
    }
    Maker(int id, int age)
    {
        this->id = id;
        this->age = age;
    }
public:
    int id;
    int age;
};
​
void test()
{
    Maker m1(10, 20);
    Maker m2;
​
    m2 = m1;//赋值操作
    //默认的赋值运算符重载函数进行了简单的赋值操作
    cout << m2.id << " " << m2.age << endl;
}

3.当类有成员指针时,然后在构造函数中申请堆区空间,在析构函数中释放堆区空间,会出现同一块空间释放2次,然后内存泄漏,所以要重写赋值运算符重载函数

class Student
{
public:
    Student(const char *name)
    {
        pName = new char[strlen(name) + 1];
        strcpy(pName, name);
    }
    //防止浅拷贝
    Student(const Student &stu)
    {
        pName = new char[strlen(stu.pName) + 1];
        strcpy(pName, stu.pName);
    }
    //重写赋值运算符重载函数
    Student &operator=(const Student &stu)
    {
        //1.不能确定this->pName指向的空间是否能装下stu中的数据,所以先释放this->pName指向的空间
        if (this->pName != NULL)
        {
            delete[] this->pName;
            this->pName = NULL;
        }
​
        //2.申请堆区空间,大小由stu决定
        this->pName = new char[strlen(stu.pName) + 1];
        //3.拷贝数据
        strcpy(this->pName, stu.pName);
​
        //4.返回对象本身
        return *this;
    }   
​
    ~Student()
    {
        if (pName != NULL)
        {
            delete[] pName;
            pName = NULL;
        }
    }
​
    void printStudent()
    {
        cout << "Name:" << pName << endl;
    }
public:
    char *pName;
};
​
void test02()
{
    Student s1("悟空");
    Student s2("小林");
​
    s1.printStudent();
    s2.printStudent();
​
    s1 = s2;//赋值操作
​
    s1.printStudent();
    s2.printStudent();
    
    //复数运算不会出错
    //s1 = s2 = s3;
}

4.赋值运算符重载函数中,为什么要返回引用

void test03()
{
    Student s1("a");
    Student s2("b");
    Student s3("c");
​
    s1 = s2 = s3;//s3赋值s2,s2赋值给s1
​
    cout << &(s2 = s3) << endl;
    cout << &s2 << endl;
    //如果返回的是值,s2=s3这个表达式会产生一个新的对象
    //s1=s2=s3,赋值运算符本来的寓意,是s3赋值s2,s2赋值给s1
    //也就是说s2=s3这个表达式要返回s2这个对象,所以要返回引用
​
}

5.关系运算符重载

class Maker
{
public:
    Maker()
    {
        id = 0;
        age = 0;
    }
    Maker(int id, int age)
    {
        this->id = id;
        this->age = age;
    }
​
    bool operator==(Maker &m)
    {
        if (this->id == m.id && this->age == m.age)
        {
            return true;
        }
        return false;
    }
​
​
    bool operator!=(Maker &m)
    {
        if (this->id != m.id || this->age != m.age)
        {
            return true;
        }
        return false;
    }
public:
    int id;
    int age;
};
​
void test()
{
    Maker p1(1, 20);
    Maker p2;
​
    if (p1 == p2)
    {
        cout << "真" << endl;
    }
    else
    {
        cout << "假" << endl;
    }
​
    if (p1 != p2)
    {
        cout << "真" << endl;
    }
    else
    {
        cout << "假" << endl;
    }
}

6.前置加加和后置加加运算符重载

class Maker
{
    friend ostream &operator<<(ostream &out, Maker &m);
public:
    Maker(int a)
    {
        this->a = a;
    }
    //重载前置加加
    Maker &operator++()
    {
        ++this->a;
        return *this;
    }
​
    //后置加加,
    Maker operator++(int)//占位参数,必须是int
    {
        //后置加加,先返回,后加加
        Maker tmp(*this);//1.*this里面的值a是等于2
        ++this->a;//这个对象的a等3
        return tmp;
    }
private:
    int a;
};
​
ostream &operator<<(ostream &out, Maker &m)
{
    out << m.a << endl;
    return out;
}
​
void test02()
{
    Maker m1(1);
    cout << m1 << endl;//1
    cout << ++m1 << endl;//2
    //++(++m1);
    cout << m1++ << endl;//2  这里返回的拷贝的tmp对象
    cout << m1 << endl;//3 这里返回的是++this->a的对象
​
    //同等条件下,优先使用前置加加,不需要产生新的对象和调用拷贝构造
​
}

7.数组下标运算符重载

MyArray.h
class MyArray
{
public:
//重写赋值运算符重载函数
    MyArray&operator=(const MyArray &m);
​
    //要能当左右值
    int &operator[](int index);
​
};
​
MyArray.cpp
//重写赋值运算符重载函数
MyArray&MyArray::operator=(const MyArray &m)
{
    cout << "赋值函数" << endl;
    //1.释放原来的空间
    if (this->pArray != NULL)
    {
        delete[] this->pArray;
        this->pArray = NULL;
    }
    this->mCapacity = m.mCapacity;
    this->mSize = m.mSize;
    //2.申请空间,大小由m决定
    this->pArray = new int[m.mCapacity];
    //3.拷贝数据
    cout << "this->mSize:"<<this->mSize << endl;
    for (int i = 0; i < this->mCapacity; i++)
    {
        this->pArray[i] = m.pArray[i];
    }
​
    return *this;
}
​
//要能当左右值
int &MyArray::operator[](int index)
{
    /*
    for (int i = 0; i < 20; i++)
    {
        arr[i] = i + 10;
    }
​
    for (int i = 0; i < 20; i++)
    {
        cout << arr[i] << " ";
    }
    */
    //赋值时,加加
    
    
    if (this->mSize <=index)
    {
        this->mSize++;
    }
    
    return this->pArray[index];
}
​
数组下标重载.cpp
void test02()
{
    MyArray arr;
    for (int i = 0; i < 20; i++)
    {
        arr[i] = i + 10;
    }
​
    for (int i = 0; i < 20; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
    MyArray arr2;
    arr2 = arr;
    for (int i = 0; i < 20; i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;
    cout << arr2.Size() << endl;
}

8.指针运算符重载、函数重载、其他

#include <iostream>
#include <string>
using namespace std;

class Person {
	friend class SmartPoint;
public:
	int id;
	string name;
public:
	Person() {}
	Person(int id, string name):id(id),name(name) {}
	~Person() {
		cout << "Hello" << endl;
	}
};

class SmartPoint {
public:
	SmartPoint(Person *p) {
		this->p = p;
	}
	~SmartPoint() {
		if (this->p != NULL) {
			delete this->p;
			this->p = NULL;
		}
	}
	Person* operator->() {
		return this->p;
	}
	Person& operator*() {
		return *this->p;
	}
	void operator()() {
		cout <<"id:" << this->p->id << " name:" << this->p->name << endl;
	}
	void operator()(string str) {
		cout << "id:" << this->p->id << " name:" << this->p->name <<" " << str << endl;
	}
	operator bool() {
		if (this->p->id>1) {
			return true;
		}
		else {
			return false;
		}
	}
	bool operator !() {
		if (this->p->id > 1) {
			return false;
		}
		else {
			return true;
		}
	}
	operator int() {
		return this->p->id;
	}
private:
	Person* p;
};

void test() {
	Person *p1=new Person(1,"Andy");
	SmartPoint sp(p1);
	cout << sp->name << endl;
	cout<<(*sp).name << endl;
	sp("函数重载");
	sp();
	if (sp) {
		cout << "ture" << endl;
	}
	else {
		cout << "false" << endl;
	}
	if (!sp) {
		cout << "ture" << endl;
	}
	else {
		cout << "false" << endl;
	}
	int b = (int)sp;
	cout << "b=" << b << endl;
}

int main() {
	test();
	system("pause");
	return EXIT_SUCCESS;
}

本文含有隐藏内容,请 开通VIP 后查看