总结:
1、运算符重载的本质是函数重载
2、运算符重载可分为成员函数重载和全局函数重载(差一个参数)
3、运算符重载函数的参数至少有一个是类对象(或类对象的引用)
4、不可以被重载的操作符有:成员选择符(.) 成员对象选择符(.*)
域解析操作符(::) 条件操作符(?:)
5、前置加加 可以连续使用 后置加加 不可以连续使用
6、前置加加(减减)的运算符重载和普通运算符重载一样,后置加加(减减)的运算符重载需要加一个占位符
7、输入输出运算符重载定义为全局函数重载。因为成员函数重载会发生歧义
8、输入输出运算符重载借助输入输出流(ostream istream)
9、双目运算符就是有两个参数(+,-),单目运算符有一个参数(++,--)
10、重载的前置加加 Complex& operator++(Complex &c1) //返回引用的目的是使用连续前置加加
重载的后置加加 const Complex& operator++(Complex &c1, int)
//加const的原因是后置加加不能连续使用
11、右移操作符重载:friend ostream& operator<<(ostream &os, Complex &c);
ostream& operator<<(ostream &os) //c1.operator<<(cout)
{
os << "(" << this->a << "," << this->b << "i)";
return os;
}
左移操作符重载:friend istream& operator>>(istream &is, Complex &c);
istream& operator>>(istream &is, Complex &c)
{
cout << "a:";
is >> c.a;
cout << "b:";
is >> c.b;
return is;
}
12、若某函数中类想引用私有成员,则将此函数在这个类中声明为友元函数
13、除了赋值号(=)外,基类中被重载的操作符都将被派生类继承
1、操作符重载格式
重载函数的一般格式如下:
函数类型 operator 运算符名称(形参表列) {
重载实体;
}
operator 运算符名称 在一起构成了新的函数名。比如
const Complex operator+(const Complex &c1,const Complex &c2);
我们会说,operator+ 重载了重载了运算符+。
2、重载规则
4.10.2 重载规则
(1)C++不允许用户自己定义新的运算符,只能对已有的 C++运算符进行重载。
例如,有人觉得 BASIC 中用“* *”作为幂运算符很方便,也想在 C++中将“**”定义为幂运算符,用“3**5”表示 35,这是不行的。
(2)C++允许重载的运算符
C++中绝大部分运算符都是可以被重载的。
不能重载的运算符只有 4 个:成员选择符(.) 成员对象选择符(.*) 域解析操作符(::) 条件操作符(?:)
前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符合sizeof 运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征。
3)重载不能改变运算符运算对象(即操作数)的个数。
如,关系运算符“>”和“<”等是双目运算符,重载后仍为双目运算符,需要两 个参数。运算符”+“,”-“,”*“,”&“等既可以作为单目运算符,也可以作为双 目运算符,可以分别将它们重载为单目运算符或双目运算符。
4)重载不能改变运算符的优先级别。
例如”*“和”/“优先级高于”+“和”-“,不论怎样进行重载,各运算符之间的优先级不会改变。有时在程序中希望改变某运算符的优先级,也只能使用加括号的方法 强制改变重载运算符的运算顺序。
(5)重载不能改变运算符的结合性。
如,复制运算符”=“是右结合性(自右至左),重载后仍为右结合性。
(6)重载运算符的函数不能有默认的参数
否则就改变了运算符参数的个数,与前面第(3)点矛盾。
(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有 一 个是类对象(或类对象的引用)。
也就是说,参数不能全部是 C++的标准类型,以防止用户修改用于标准类型数据成 员的运算符的性质,
(8)用于类对象的运算符一般必须重载,但有两个例外,运算符”=“和运算 符”&“不 必用户重载。
复制运算符”=“可以用于每一个类对象,可以用它在同类对象之间相互赋值。因为系统已为每一个新声明的类重载了一个赋值运算符,它的作用是逐个复制类中的 数据成员地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
(9)应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能。
例如,我们会去重载”+“以实现对象的相加,而不会去重载”+“以实现对象相 减的功能,因为这样不符合我们对”+“原来的认知。
(10)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数
操作符重载
#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}friend Complex complexAdd(Complex &c1, Complex &c2);/*friend Complex operator+(Complex &c1, Complex &c2);friend Complex operator-(Complex &c1, Complex &c2);*/Complex complexAdd(Complex &another){Complex temp(this->a + another.a, this->b + another.b);return temp;}//2操作符重载写在局部Complex operator+(Complex &another){Complex temp(this->a + another.a, this->b + another.b);return temp;}Complex operator-(Complex &another){Complex temp(this->a - another.a, this->b - another.b);return temp;}private:int a;//实数int b;//虚数
};Complex complexAdd(Complex &c1, Complex &c2)
{Complex temp(c1.a + c2.a, c1.b + c2.b); //要访问需要声明为友元函数return temp;
}
void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();Complex c3 = complexAdd(c1, c2);c3.printComplex();
}void test02() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();Complex c3 = c1.complexAdd(c2);c3.printComplex();
}
//1操作符重载写在全局
#if 0
Complex operator+(Complex &c1, Complex &c2) //+ 相当于函数名,接收两个参数//+ 左边是 第一个参数//+ 右边是 第二个参数 顺序固定
{Complex temp(c1.a + c2.a, c1.b + c2.b);return temp;
}Complex operator-(Complex &c1, Complex &c2)
{Complex temp(c1.a - c2.a, c1.b - c2.b);return temp;
}#endif
//全部操作符重载调用
void test03() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();//Complex c3 = operator+(c1, c2); //ok//等价于Complex c3 = c1 + c2; //此种为隐式写法// c1 + c2 等价于 operator+(c1,c2) 全局的调用方式// c1 + c2 也等价于 c1.operator+(c2) 局部调用方式//所以局部调用方式和全局调用方式只能存在一个c3.printComplex();
}
void test04() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();//Complex c3=c1.operator+(c2);//等价于Complex c3 = c1 + c2;c3.printComplex();Complex c4 = c1 - c2;c4.printComplex();Complex c5 = c1-c2-c1; //当 operator-函数 返回为元素时ok //c1-c2返回为匿名对象 //再调用函数 还为匿名对象 拷贝构造给c5//当 operator-函数返回引用时 错误 //c1-c2返回为为temp的别名//再调用函数时 temp已经析构 c1-c2变为乱码 再调用函数仍然为乱码c5.printComplex();
}
int main(void)
{cout << "------test01-----------" << endl;test01();cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();return 0;
}
#endif
双目运算符(有两个参数):
#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:/*friend Complex& operator+=(Complex &c1, Complex &c2);friend Complex& operator-=(Complex &c1, Complex &c2);*/Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}//2操作符重载写在局部Complex& operator+=(Complex &another){this->a += another.a;this->b += another.b;return *this;}Complex& operator-=(Complex &another){this->a -= another.a;this->b -= another.b;return *this;}private:int a;//实数int b;//虚数
};//1操作符重载写在全局
#if 0
Complex& operator+=(Complex &c1, Complex &c2) //+ 相当于函数名,接收两个参数//+ 左边是 第一个参数//+ 右边是 第二个参数 顺序固定
{c1.a += c2.a;c1.b += c2.b;return c1;
}Complex& operator-=(Complex &c1, Complex &c2)
{c1.a -= c2.a;c1.b -= c2.b;return c1;
}#endif
void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();(c1 += c2)+=c2; //(c1.operator+=(c2)).operator(c2)c1.printComplex();c2.printComplex();
}
/*
( 1, 2i )
( 2, 4i )
( 5, 10i )
( 2, 4i )
*/
//全部操作符重载调用int main(void)
{cout << "------test01-----------" << endl;test01();/*cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0;
}
#endif
单目运算符:
#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:/*friend Complex& operator++(Complex &c1);friend Complex& operator--(Complex &c12);friend const Complex& operator++(Complex &c1, int);*/Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}//2操作符重载写在局部Complex& operator++(){this->a ++;this->b ++;return *this;}Complex& operator--(){this->a --;this->b --;return *this;}const Complex& operator++(int) { //亚元Complex temp(this->a, this->b);this->a++;this->b++;return *this;}private:int a;//实数int b;//虚数
};//1操作符重载写在全局
#if 0
//重载的前置加加
Complex& operator++(Complex &c1) //+ 相当于函数名,接收两个参数//+ 左边是 第一个参数//+ 右边是 第二个参数 顺序固定
{c1.a ++;c1.b ++;return c1;
}Complex& operator--(Complex &c1)
{c1.a--;c1.b--;return c1;
}#endif
//重载的后置加加 不可以用多次 所以用const限制
#if 0
const Complex& operator++(Complex &c1, int) { Complex temp(c1.a, c1.b);c1.a++;c1.b++;return c1;
}
#endif
void test01() {Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();++c1;c1.printComplex();/*++c1;c1.printComplex();*/}
/*
( 1, 2i )
( 2, 4i )
( 2, 3i )
( 3, 4i )
*/
void test02() {int a = 0;//a++++; 编译错误 后置加加不可多次Complex c1(1, 2);Complex c2(2, 4);c1.printComplex();c2.printComplex();c1++; //后置加加返回值添加const 使得c1++++ 编译错误c1.printComplex();
}
/*
( 1, 2i )
( 2, 4i )
( 2, 3i )
*/
int main(void)
{cout << "------test01-----------" << endl;test01();cout << "------test02-----------" << endl;test02();/*cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0;
}
#endif
左移右移操作符:
#if 1
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;class Complex
{
public:friend ostream& operator<<(ostream &os, Complex &c);friend istream& operator>>(istream &is, Complex &c);Complex(int a, int b){this->a = a;this->b = b;}void printComplex(){cout << "( " << this->a << ", " << this->b << "i )" << endl;}
#if 0//左移操作符只能不能够写在成员函数里 只能写在全局函数中 否则调用顺序会变反 c1<<cout;ostream& operator<<(ostream &os) { //c1.operator<<(cout)os << "(" << this->a << "," << this->b << "i)";return os;}
#endif//2操作符重载写在局部private:int a;//实数int b;//虚数
};//1操作符重载写在全局
#if 1
//重载的前置加加
ostream& operator<<(ostream &os, Complex &c) {os << "(" << c.a << "," << c.b << "i)";return os;
}
istream& operator>>(istream &is, Complex &c) {cout << "a:";is >> c.a;cout << "b:";is >> c.b;return is;
}
#endifvoid test01() {Complex c1(1, 2);Complex c2(2, 4);cout << c1 << endl;cin >> c2;c1.printComplex();c2.printComplex();//cout << c1; //operator<<(cout,c1) 全局ok 局部不ok//c1 << cout; ok}
/**/int main(void)
{cout << "------test01-----------" << endl;test01();/*cout << "------test02-----------" << endl;test02();cout << "------test03-----------" << endl;test03();cout << "------test04-----------" << endl;test04();*/return 0;
}
#endif