运算符重载
- **运算符重载的概念**
- **加号运算符重载**
- **减号运算符重载**
- **左移运算符重载**
- **右移运算符重载**
- **赋值运算符重载**
- **关系运算符重载**
- **前置加加和后置加加**
运算符重载的概念
1.运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
2.运算符重载的目的是让语法更加简洁
3.运算符重载不能改变本来寓意,不能改变基础类型寓意
4.运算符重载的本质是另一种函数调用(是编译器去调用)
5.这个函数同一的名字叫operator
6.重载函数可以写成全局或成员函数
7.重载函数如果写成全局的,那么双目运算符左边的是第一个参数,右边是第二个参数
8.重载函数如果写成成员函数,那么双目运算符的左边是this,右边是第一个参数
9.不能改变运算符优先级,不能改变运算符的参数个数
短路规则是:与运算前面假就假后面无需判断,或者是或运算前面真就真后面无需判断
加号运算符重载
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
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;
};
//全局方式 //2、编译器调用这个函数
//Maker operator+(Maker &p1,Maker &p2)//3、编译器检查参数是否对应
//{
// 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;//先是m2+m3
cout << "id:" << m4.id << "age:" << m4.age << endl;
}
//不同类型的加法运算符重载
class Student
{
public:
Student()
{
mid = 0;
}
Student(int id)
{
mid = id;
}
public:
int mid;
};
//返回值是任意一个类都行
Maker operator+(Maker &m,Student &s)
{
Maker tmp(m.id + s.mid, 20);//20随便传的一个参数
return tmp;
}
Maker operator+(Student &s,Maker &m)
{
Maker tmp(s.mid + m.id,20);//20随便传的一个参数
return tmp;
}
void test()
{
Maker m1(1, 18);
Student s1(2);
Maker m2 = m1 + s1;
Maker m3 = s1 + m1;
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
减号运算符重载
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Maker
{
public:
Maker(int id)
{
this->id = id;
}
public:
int id;
//写成成员函数,那么只需要一个参数,这个参数是减号的右边
Maker operator-(Maker &m2)
{
Maker tmp(this->id - m2.id);
return tmp;
}
};
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;
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
左移运算符重载
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <string>
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的对象
//cout其实是个类
//void operator<<(ostream &out,Maker &m)
ostream& operator<<(ostream &out,Maker &m)
{
cout << m.id << " " << m.name << endl;
return out;
}
void test01()
{
Maker m(10,"露琪亚");
//对应的上面第一个void operator的注释
//cout << m.id << endl;//现在就是err 因为返回的是void
cout << m << endl;
cout << m;//返回的是void
cout << endl;//endl是内联函数
/*endl是一个函数
operator<<(函数指针)
operator<<(endl)
*/
cout << 10;//内部重载了基础数据类型
cout << endl;
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
右移运算符重载
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include<string>
void test()
{
int a;
cin >> a;
cout << a << endl;
}
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("悟空", 15);
cin >> m >> m2;
cout << m.getAge() << endl;
cout << m2.getAge() << endl;
}
int main()
{
test02();
system("pause");
return EXIT_SUCCESS;
}
赋值运算符重载
编译器默认给类提供了一个默认的赋值运算符重载函数
默认的赋值运算符重载函数进行了简单的赋值操作
当类有成员指针时,然后在构造函数中申请堆区空间,在析构函数中释放堆区空间
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
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;
}
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)
//如果不返回&的话相当于是Student operator=s1 相当于调用了一次拷贝构造函数
{
//1.不能确定this->pName指向的空间是否能装下stu中的数据,所以先释放thist指向的空间
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;//*this返回的是对象的本身 s1 s2 s3
}
~Student()
{
if (pName!=NULL)
{
delete[] pName;
pName = NULL;
}
}
void printStudent()
{
cout << "pName:" << pName << endl;
}
public:
char *pName;
};
void test02()
{
Student s1("卡卡罗特");
Student s2("露琪亚");
s1.printStudent();
s2.printStudent();
s1 = s2;//赋值操作 析构函数会导致同一块空间被释放两次
//还会导致内存泄露
s1.printStudent();
s2.printStudent();
//s1 = s2 = s3;
}
void test03()
{
Student s1("a");
Student s2("b");
Student s3("c");
s1 = s2 = s3;//赋值操作
cout << &(s2 = s3) << endl;
cout << &s2 << endl;
}
int main()
{
//test02();
test03();
system("pause");
return EXIT_SUCCESS;
}
关系运算符重载
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
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 test01()
{
Maker p1(1, 20);
Maker p2;
if (p1 == p2)
{
cout << "真" << endl;
}
else
{
cout << "假" << endl;
}
if (p1 != p2)
{
cout << "真" << endl;
}
else
{
cout << "假" << endl;
}
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
前置加加和后置加加
/你的第二个operator++返回了一个临时变量,这个在C++里面是一个右值(简单来说就是只能放在 = 号右边)
而你重载的 << 操作符号第二个参数是一个非const的引用,非const的引用需要一个左值(可以放在 = 号左边,可以赋值)来初始化,因此报错
解决办法很简单,把你重载的 << 符号第二个参数加上const修饰即可。加了const修饰的引用可以用右值来初始化/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <string>
void test()
{
int a = 1;
cout << ++a << endl;
cout << a++ << endl;
cout << a << endl;
++(++a);
}
class Maker
{
friend ostream &operator<<(ostream &out, Maker const &m);
public:
Maker(int a)
{
this->a = a;
//cout << "1" << endl;
}
//重载前置++
Maker &operator++()
{
++this->a;
return *this;
}
//重载后置++
//这里不用引用 是因为
//如果返回引用这里是返回局部的引用 在这个函数执行完时,被释放掉了
Maker operator++(int)//区分后置++ //占位参数,必须是int
{
//后置++,先返回,后++
Maker tmp(*this); //1、*this里面的值a是等于2的
++this->a; //这个对象的a是等于3的
return tmp;//返回的是右值常量 零时变量 调用一次构造函数
/*你的第二个operator++返回了一个临时变量,这个在C++里面是一个右值(简单来说就是只能放在 = 号右边)
而你重载的 << 操作符号第二个参数是一个非const的引用,非const的引用需要一个左值(可以放在 = 号左边,可以赋值)来初始化,因此报错
解决办法很简单,把你重载的 << 符号第二个参数加上const修饰即可。加了const修饰的引用可以用右值来初始化*/
/* cout << "后置加加" << endl;
return Maker(10);*/
}
private:
int a;
};
ostream &operator<<(ostream &out, Maker const &m)
{
out << m.a << endl;
return out;
}
void test01()
{
Maker m1(1);
//cout << m1 << endl;//1
//cout << ++m1 << endl;//2
cout << (m1++) << endl;//2
//cout << m1 << endl;//3
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}