运算符重载概念:对已有的运算符重新进行定义,赋予另一种功能,适应不同的数据类型。
1、加号运算符重载 +
实现两个自定义数据类型相加的运算
1、成员函数重载+号
class Person { pubilc: Person operator+(Person &p)//重载+号 { Person temp; temp.m_A = this->m_A + p.m_A; temp.m_B = this->m_B + p.m_B; return temp; } int m_A; int m_B; };
2、全局函数做重载+号
class Person { public: int m_A; int m_B; }; 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 p3 = p1.Person(p2);//成员函数做重载+号 Person p3 = Person(p1,p2);//全局函数做重载+号 //以上都可以写成以下形式: Person p3 = p1 + p2;
总结:
1、对于内置的数据类型的表达式的的运算符是不可能改变的
2、不要滥用运算符重载(加不能做其他运算,只能加)
2、左移运算符重载 <<
作用:可以输出自定义数据类型(只能在全局函数中写)
ostream & operator<<(ostream &cout,Person &p) { cout << "m_A=" << p.m_A << "m_B=" << p.m_B; return cout; } //cout的本质是输出流也就是ostream
总结:重载左移运算符配合友元可以实现输出自定义数据类型
下面是案例:
class Person { public: int m_A; int m_B; }; class Eat { public: int food; int write; }; ostream& operator<<(ostream& cout, Person& p) { cout << "a=" << p.m_A << "b=" << p.m_B;//重载<<,如果和p不匹配,直接返回cout的内容 return cout; } int main() { Person p1; Eat p2; p1.m_A = 10; p1.m_B = 20; p2.food = 30; p2.write = 40; cout << p1 << "eat=" << p2.food << endl;//结果为a=10b=20eat=30 return 0; }
3、递增运算符重载 ++
作用:通过递增运算符,实现自己的整型数据
class MyInteger { friend ostream& operator<<(ostream& cout, MyInteger& p); public: MyInteger() { m_Num = 0; } //重载前置++运算符 MyInteger& operator++() { m_Num++; return *this; } //重载后置++运算符 MyInteger& operator++(int) { MyInteger temp = *this; m_Num++; return *this; } private: int m_Num; }; void test() { MyInteger intmy; cout << ++intmy << endl; } int main() { test(); return 0; }
4、赋值运算符重载 =
深拷贝
class Person { public: Person(int age) { m_Age = new int(age); } Person& operator=(Person &p) //做深拷贝 { if(m_Age != NULL) { delete m_Age; m_Age =NULL; } m_Age = new int(*p.m_Age); //重新创建就有新的空间 return *this; } ~Person() { if(m_Age != NULL) { delete m_Age; m_Age =NULL; } } int m_Age; };
5、关系运算符重载 == !=
作用:让两个自定义类型对象进行对比
class Person { public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } bool operator==(Person &p)//重载== { if(this->m_Name == p.m_Name && this->m_Age == p.m_Age) { return true; } else { return false; } } bool operator!=(Person &p)//重载!= { if(this->m_Name == p.m_Name && this->m_Age == p.m_Age) { return false; } else { return true; } } private: string m_Name; int m_Age; };
6、函数调用运算符重载 ()
由于重载后使用的方式非常像函数调用,因此也称为仿函数
class MyPrint { public: void operator()(string text) { cout << text << endl; } };
注意事项:
A、除成员访问运算符“.”、成员指针运算符“.*”和“->*”、作用域运算符“::”、sizeof运算符和三目运算符“?:”、预处理符号“#”以外,C++中的所有运算符都可 以重载(其中“=”和“&”不必用户重载)
B、重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符
C、运算符重载的实质是函数重载,遵循函数重载的选择原则
D、重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构
E、运算符重载不能改变该运算符用于内部类型对象的含义
F、运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符
G、重载运算符的函数不能有默认的参数,否则就改变了运算符的参数个数
H、重载的运算符只能是用户自定义类型,否则就不是重载而是改变了现有的C++标准数据类型的运算符的规则
I、运算符重载可以通过成员函数的形式,也可是通过友元函数,还可以是非成员函数的形式。