什么是运算符重载
对于基本类型 int a, b, c;
执行运算 c = a + b;
,编译器很容易理解,但是对于对象 ClassA a0, a1, a2;
执行运算 a0 = a1 + a2;
,编译器就懵了。对于下面一段代码,在函数 test_operateplus()
中,执行op = op + op1;
时,程序调用 OperatePlus operator+(const OperatePlus &val)
对两个对象的成员变量进行求和,此即为运算符重载。
class OperatePlus
{
public:
OperatePlus(int _a, int _b);
~OperatePlus();
OperatePlus operator+(const OperatePlus &val); //重载运算符 `+`
void print_result();
private:
int a, b;
};
OperatePlus::OperatePlus(int _a, int _b)
{
a = _a;
b = _b;
}
OperatePlus::~OperatePlus() { }
OperatePlus OperatePlus::operator+(const OperatePlus &val)
{
return OperatePlus(this->a + val.a, this->b + val.b);
}
void OperatePlus::print_result()
{
cout << "a:" << a << " b:" << b << endl;
}
void test_operateplus()
{
OperatePlus op(1, 2), op1(3, 4);
op = op + op1;
op.print_result(); //打印结果 a:4 b:6
}
为什么要对运算符重载
为了实现对象的运算符操作,充分发挥面向对象的思想,使得用户自定义的数据以一种更简洁的方式工作。例如复数运算,矩阵运算。
运算符重载语法
返回值类型 类名::operator#(list)
{
...
}
#
为要重载的运算符,list
为参数表。
可以重载的运算符太多,所以只列出不能重载的运算符:
. | :: | .* | ?: | sizeof |
---|
运算符重载的两种方法
可以用成员或友元函数重载运算符 ,关键区别在于成员函数具有 this 指针,友元函数没有this指针,所需操作数都必须在参数表显式声明。不管是成员函数还是友元函数重载,运算符的使用方法相同。
成员函数重载运算符见第一段代码,友元法改造如下:
class OperatePlus
{
public:
friend OperatePlus operator+(const OperatePlus &op1, const OperatePlus &op2);
...
};
OperatePlus operator+(const OperatePlus &op1, const OperatePlus &op2)
{
OperatePlus op(op1.a + op2.a, op1.b + op2.b);
return op;
}
void test_friend_operateplus()
{
OperatePlus op(1, 2), op1(3, 4);
op = operator+(op, op1); //op = op + op1; 两种调用方式均可
op.print_result();
}
需要注意的是 =
,()
,[]
,->
不能用友元函数重载。
典型的运算符重载
++
class AutoAdd
{
public:
AutoAdd(int _a = 0);
AutoAdd& operator++(); /*implement as preposition*/
AutoAdd operator++(int );/*implement as postposition*/
void print_val();
~AutoAdd();
private:
int a;
};
AutoAdd::AutoAdd(int _a) { a = _a; }
AutoAdd::~AutoAdd() {}
//preposition 前置 ++
AutoAdd& AutoAdd::operator++()
{
this->a++;
return *this;
}
//postposition 后置 ++
AutoAdd AutoAdd::operator++(int )
{
AutoAdd aa = *this;
this->a++;
return aa;
}
void AutoAdd::print_val() { cout << a << endl; }
void test()
{
AutoAdd t(10), t1(0);
t1 = ++t; //preposition
t.print_val(); // 11
t1.print_val(); // 11
t1 = t.operator++(1); //postposition
t.print_val(); //12
t1.print_val(); //11
}
=
重载,解决指针浅拷贝问题
#include <cstring>
class StoreString
{
public:
StoreString();
StoreString(const char *c);
//StoreString(StoreString &s);
StoreString& operator=(const StoreString &s);
void printString();
~StoreString();
private:
char *p;
int len;
};
/*
StoreString::StoreString(StoreString &s)
{
len = s.len;
p = new char[len+1];
strcpy_s(p, len+1, s.p);
}
*/
StoreString::StoreString(){ }
StoreString::StoreString(const char *c)
{
len = strlen(c);
p = new char[len+1];
strcpy_s(p, len+1, c);
}
StoreString::~StoreString()
{
if (p != NULL) {
delete[] p;
p = NULL;
len = 0;
}
}
StoreString& StoreString::operator=(const StoreString &s)
{
if (this->p != NULL)
{
delete[] p;
len = 0;
}
this->len = s.len;
this->p = new char[len+1];
strcpy_s(p, len+1, s.p);
return *this;
}
void StoreString::printString() { cout << p << endl;}
void testEqu()
{
StoreString ss("abc");
StoreString ss1("def");
StoreString ss2;
ss2 = ss1 = ss; //=重载返回引用可以做连=操作,顺序从右到左
ss1.printString();
ss2.printString();
}
数组类的 [] == !=
都类似就不一一列举了。。