一、运算符重载
再讨论运算符重载之前我们先来介绍下函数重载,函数重载就是对一个已有的函数
赋予新的含义,使之实现新功能,因此一个函数名就可以代表不同功能的函数
运算符重载:简单点来说就是赋予 运算符 一个新的功能,新的运算规则
当然了基础数据类型编译器知道运算规则,所以可以直接运算
下面来介绍下运算符重载的步骤:
1、写出函数名 operator + 重要的运算符 (比如+:operator+, *: operator* []: operator[])
2、根据运算需要的操作数写出 参数列表,加法需要两个操作数,分别写出左和右操作数:operator+(c1, c2);
3、根据需要写出函数返回值:Complex operator+(const Complex &c1, const Complex &c2)
class Complex
{
friend Complex add (const Complex &c1, const Complex &c2);
friend Complex operator+(const Complex &c1, const Complex &c2);
friend Complex operator+(const Complex &c1, int num);
public:
Complex()
{
a = 0;
b = 0;
}
Complex(int a, int b)
{
this->a = a;
this->b = b;
}
void print()
{
printf ("%d + %di\n", a, b);
}
Complex add(const Complex &c2)
{
Complex tmp(a+c2.a, b+c2.b);
return tmp;
}
Complex operator-(const Complex &c2) const
{
Complex tmp(a-c2.a, b-c2.b);
return tmp;
}
private:
int a; // 实部
int b; // 虚部
};
Complex add(const Complex &c1, const Complex &c2)
{
Complex tmp(c1.a+c2.a, c1.b+c2.b);
return tmp;
}
// 全局函数
// operator+ 可以理解成一个函数名
Complex operator+(const Complex &c1, const Complex &c2)
{
Complex tmp(c1.a+c2.a, c1.b+c2.b);
return tmp;
}
Complex operator+(const Complex &c1, int num)
{
Complex tmp(c1.a + num, c1.b);
return tmp;
}
int main3_2()
{
Complex c1(1,2), c2(3,4), c;
// c = c1 + c2;
// 全局使用
c = operator+(c1, c2);
// 内部使用
c = c1.add(c2);
// 运算符重载 内部 和 全局函数 同时只能存在一个
// 全局到内部的转换:隐藏左操作数
c = c1.operator-(c2);
c = c1 - c2;
c.print();
return 0;
}
二、单目运算符
前置自增运算符
int main4_1()
{
Complex c(1,2), c2(3,4);
// 复数自增 实部虚部同时自增
// operator ++
// operator ++(c) ====> operator ++(Complex &c)
// void operator ++(Complex &c)
// ++c;
// c.print();
Complex c1 = ++c; // Complex c1 = operator ++(c)
c1 = ++c + c2; // c1 = ++c + c2; (operator ++(c)).operator+(c2)
c1.print();
// 内部 Complex& operator --(Complex &c) ===> Complex& operator --()
--c1;
c1.print();
return 0;
}
后置自增运算符
// 后置++ 有一个占位参数来与 前置++进行区分
// 先使用,再自增
Complex operator++(Complex &c, int)
{
// 定义一个临时对象来保存 c 的值
Complex tmp(c.a, c.b);
c.a++;
c.b++;
return tmp;
}
// 后置自增运算符:c++
int main()
{
Complex c, c1(1,2),c2(3,4);
// Complex operator++(Complex &c, int)
c = c1++ + c2;
c.print();
c1.print();
// 内部 :Complex operator--(Complex &c, int) ====> Complex operator--(int)
c1--;
c1.print();
return 0;
}
三、左移与右移操作符
<< 是一个操作符 我们可以重载它的功能
cout 是一个对象 cout 是 ostream 的一个对象
operator<< (cout, c1)
operator<< (ostream &out, const Complex &c);
左移和右移操作只能用友元函数进行重载,写成全局函数,无法写成内部函数,因为无法修改 ostream 类
四、赋值运算符
Teacher &operator=(const Teacher &obj)
{
// 函数入口参数检查 如果是自己直接返回
if (&obj == this)
return *this;
// 1、释放原有的空间
if (name != NULL)
delete [] name;
// 2、开辟新空间
this->name = new char[20];
// 复制
this->age = obj.age;
strcpy (this->name, obj.name);
return *this;
}
默认的赋值运算是一个 浅拷贝 的过程
五、函数调用运算符
class Test
{
public:
Test(int a)
{
this->a = a;
}
void operator()(int b1, int b2)
{
printf ("a = %d\n", a);
}
private:
int a;
};
int main7_1()
{
// 定义对象
Test a(10);
// ()是函数调用运算符
// operator()(Test &a) ===> operator()()
a(1, 2); // a 是一个对象, 不是一个函数, 但是它的行为和函数很像, 这样的使用 叫仿函数
return 0;
}
六、逻辑运算符
逻辑运算符的短路规则:
|| 有一个表达式为真,后面的表达式将不再执行
&& 有一个表达式为假,后面的表达式将不再执行
Test8_1 t1(0), t2(1), t3(2);
bool operator &&(Test8_1 &t1, Test8_1 &t2); ===> bool operator &&(Test8_1 &t2);
t1.operator&& (t2 = t3)
逻辑运算符重载无法实现短路运算规则
t1 && (t2 = t3);
七、数组下标运算符的重载
[]运算符用于访问数据对象的元素
重载格式类型 类::operator[](类型);
class Array
{
public:
Array (int len = 0)
{
this->len = len;
p = new int[len];
}
int &operator[](int index)
{
return p[index];
}
private:
int len;
int *p
int main()
{
Array a(10);
for (int i = 0; i < 10; i++)
{
// operator[] (Array &a, int i) ==> operator[] ( int i)
// a.operator[](i) = i;
a[i] = i;
}
return 0;
}