一、概念
所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能,因此,一个函数名就可以用来代表不同功能的函数,也就是”一名多用”。
运算符也可以重载。
又如”<<“是C++的位运算中的位移运算符(左移),但在输出操作中又是与流对 象cout 配合使用的流插入运算符,”>>“也是位移运算符(右移),但在输入操作中又是与流对象 cin 配合使用的流提取运算符。
二、实现运算符重载
1、加号重载
1、本质:函数的重载(符号左右进行传参)
2、全局函数重载
返回类型 运算符重载关键字operator 运算符 参数
#include <iostream>
using namespace std;
class Complex
{
friend Complex operator +(const Complex &c1,const Complex &c2);
private:
int a; //实部
int b; //虚部
public:
Complex(int _a,int _b)
{
this->a = _a;
this->b = _b;
}
void print()
{
cout << a << "+" << b << "i" << endl;
}
};
//返回类型 运算符重载关键字operator 运算符 参数
Complex operator + (const Complex &c1,const Complex &c2)
{
Complex t(0,0);
t.a = c1.a + c2.a;
t.b = c1.b + c2.b;
return t;
}
int main()
{
Complex c1(1,2);
Complex c2(2,3);
c1.print();
//c1 + c2
Complex t(0,0);
t = c1 + c2;
t.print();
return 0;
}
3、成员函数
class Complex
{
//friend Complex operator +(const Complex &c1,const Complex &c2);
private:
int a; //实部
int b; //虚部
public:
Complex(int _a,int _b)
{
this->a = _a;
this->b = _b;
}
void print()
{
cout << a << "+" << b << "i" << endl;
}
Complex operator + (const Complex &c)
{
Complex t(0,0);
t.a = this->a + c.a;
t.b = this->b + c.b;
return t;
}
};
t = c1 + c2 //编译器会转换成 t = c1.operator+(c2)
2、输出重载(只能全局函数)
1、返回值引用的作用
返回值引用的话是变量,不引用就返回常量
2、成员函数重载等价于cout.operator<<(c1);
#include <iostream>
using namespace std;
class Complex
{
//friend Complex operator +(const Complex &c1,const Complex &c2);
//friend ostream &operator <<(ostream &out,const Complex &c);
private:
int a; //实部
int b; //虚部
public:
Complex(int _a,int _b)
{
this->a = _a;
this->b = _b;
}
void print()
{
cout << a << "+" << b << "i" << endl;
}
/*ostream &operator << (ostream &out) //如果左操作数不能修改,则不能重载成成员函数
{
out << this->a << "+" << this->b <<"i";
return out;
}*/
};
//返回类型 运算符重载关键字operator 运算符 参数
/*Complex operator + (const Complex &c1,const Complex &c2)
{
Complex t(0,0);
t.a = c1.a + c2.a;
t.b = c1.b + c2.b;
return t;
}*/
//&返回变量
/*ostream &operator <<(ostream &out,const Complex &c)
{
out << c.a << "+" << c.b << "i";
return out;
}*/
int main()
{
Complex c1(1,2);
c1.print();
cout << c1 << endl; //全局函数等价于operator<<(operator<<(cout,c1),endl) 成员函数等价于cout.operator<<(c1);
return 0;
}
3、单目(一元)运算符重载
1、特殊后置++
Complex operator++(int) //通过占位参数来构成函数重载
#include <iostream>
using namespace std;
class Complex
{
friend ostream &operator<<(ostream &out,const Complex &c);
private:
int a; //实部
int b; //虚部
public:
Complex(int _a,int _b)
{
this->a = _a;
this->b = _b;
}
//后置++
Complex operator++(int) //通过占位参数来构成函数重载
{
Complex t = *this;
this->a++;
this->b++;
return t; //返回常量
}
//前置++
Complex &operator ++()
{
this->a++;
this->b++;
return *this; //返回变量
}
};
ostream &operator<<(ostream &out,const Complex &c) //const修饰常量
{
out << c.a << "+" << c.b << "i";
return out;
}
int main()
{
Complex c1(1,2);
cout << c1++ << endl;; //后置++不能作为左值使用 重载后置++不能返回引用
cout << ++c1 << endl; //可以作.....
return 0;
}
4、为什么不要重载 && 和 || 运算符
原因:违背了短路原则,所以不要重载
#include <iostream>
using namespace std;
int f1()
{
cout << "this is f1" << endl;
return 0;
}
int f2()
{
cout << "this is f2" << endl;
return 1;
}
class Complex
{
private:
int a;
int b;
public:
Complex(int a,int b)
{
this->a = a;
this->b = b;
}
Complex operator+(const Complex &c)
{
cout << "operator +" << endl;
Complex t(0,0);
t.a = this->a + c.a;
t.b = this->b + c.b;
return t;
}
bool operator&&(const Complex &c)
{
return (this->a && c.a) && (this->b && c.b);
}
};
int main()
{
if(f1() && f2()) //短路原则:如果f1()不成立,则不会执行f2()
{
cout << "helloworld" << endl;
}
Complex c1(1,1);
Complex c2(2,2);
Complex c3(1,0);
if(c1 && c2)
{
cout << "成立" << endl;
}
if(c1 && c3)
{
cout << "成立" << endl;
}
//c3.operator&&(c1 + c2) c3.operator&&(c1.operator+(c2))
if(c3 && (c1 + c2)) //违背了短路原则
{
}
return 0;
}
5、数组类(重载赋值运算符=和重载数组下标运算符【】)
#include <iostream>
using namespace std;
class Array
{
private:
int size;
int *data;
public:
Array(int s)
{
size = s;
data = new int[size];
}
int &operator[](int index) //重载【】
{
return data[index];
}
bool operator!=(const Array &a)
{
if(this->size != a.size)
{
return true;
}
for(int i = 0;i < size;i++)
{
if(this->data[i] != a.data[i])
{
return true;
}
}
return false;
}
void operator=(const Array &a) //赋值运算符只能重载成员函数
{
if( *this != a )
{
this->size = a.size;
delete this->data;
this->data = new int[size];
for(int i =0;i < size;i++)
{
this->data[i] = a.data[i];
}
}
else
{
this->data = a.data;
}
}
~Array()
{
if(data != NULL)
delete data;
}
};
int main()
{
Array a1(10); //创建数组对象
a1[0] = 100; //a1.operator[](0)
//
cout << a1[0] << endl;
Array a2(5);
a2[0] = 101;
a1 = a1; //所有类都默认重载了=运算符,但是只是简单的赋值。拷贝了地址 delete会删除两遍
cout << a1[0] << endl;
return 0;
}
6、智能指针类(->重载)自动释放,防止内存泄漏
1、auto_ptr<Test> my_memory(new Test);
//把对象的的地址传参过去
#include <iostream>
#include <memory>
using namespace std;
class Test
{
public:
Test()
{
cout << "Test构造函数" << endl;
}
void print()
{
cout << "xxx" << endl;
}
~Test()
{
cout << "Test析构函数" << endl;
}
};
void f1()
{
Test *pt = new Test;
}
void f2()
{
auto_ptr<Test> my_memory(new Test); //把对象的的地址传参过去
my_memory->print(); //my_memory.operator->(print())
}
int main()
{
//f1();
f2();
return 0;
}
三、运算符重载的限制
1、不能重载的运算符
2、只能全局函数重载的运算符
1、当无法修改左操作数的类时,使用全局函数进行重载
<< >> 输出和输入重载
3、只能通过成员函数重载
=, [], ()和->操作符只能通过成员函数进行重载