运算符重载
struct Str
{
int val = 3;
};
Str Add(Str x, Str y)
{
Str z;
z.val = x.val + y.val;
return z;
}
int main()
{
int val1 = 2;
int val2 = 3;
int val3 = val1 + val2; //分别对val1和val2求值然后相加
Str x;
Str y;
Str z = Add(x, y); //同样的功能,但是写法冗杂
Str a = x + y; //可以实现为这样的形式吗?两个Str类的对象相加会和两个int型的对象相加有不同的行为,如何定义这种行为?
std::cout << z.val << std::endl;
return 0;
}
● 使用 operator 关键字引入重载函数
struct Str
{
int val = 3;
};
auto operator+(Str x, Str y) //基于#1处的角度,operator+是函数名称,参数列表不同,构成重载+运算符
{
Str z;
z.val = x.val + y.val;
return z;
}
auto operator+(Str2 x, Str2 y) //#1: 对于Str2类型也存在两个对象相加的运算
{
//Behavior different from auto operator+(Str x, Str y)
}
int main()
{
Str x;
Str y;
Str z = x + y;
std::cout << z.val << std::endl; //OK
return 0;
}
– 重载不能发明新的运算,不能改变运算的优先级与结合性,通常不改变运算含义
auto operator@(Str x, Str y) //基本内建类型中不存在@运算
struct Str
{
int val = 3;
};
auto operator+(Str x, Str y)
{
Str z;
z.val = x.val - y.val; //符合C++标准,但是不符合加法运算符通常的含义
return z;
}
int main()
{
Str x;
Str y;
Str z = x + y;
std::cout << z.val << std::endl;
return 0;
}
– 函数参数个数与运算符操作数个数相同,至少一个为类类型
struct Str
{
int val = 3;
};
auto operator+(Str x, Str y, Str t) //Error: Overloaded 'operator+' must be a unary or binary operator (has 3 parameters)
{
Str z;
z.val = x.val + y.val;
return z;
}
int main()
{
Str x;
Str y;
Str z = x + y; //Error: Invalid operands to binary expression ('Str' and 'Str')
std::cout << z.val << std::endl;
return 0;
}
auto operator+(int x, double y) //Error: Overloaded 'operator+' must have at least one parameter of class or enumeration type
{
//Do something
}
– 除 operator() 外其它运算符不能有缺省参数
struct Str
{
int val = 3;
};
auto operator+(Str x, Str y = Str{}) //Error: Parameter of overloaded 'operator+' cannot have a default argument
{
Str z;
z.val = x.val + y.val;
return z;
}
struct Str
{
int val = 3;
auto operator()(int y = 3) //重载()运算符要类内定义,第一个小括号是运算符,第二个小括号内的int y(可以有缺省值,比如此处是3)是要放入第一个小括号内的参数
{
return val + y;
}
};
int main()
{
Str x;
std::cout << x(5) << std::endl;
std::cout << x() << std::endl;
return 0;
}
– 可以选择实现为成员函数与非成员函数
struct Str
{
int val = 3;
auto operator()(int y = 3) //隶属于类Str,因此是成员函数
{
return val + y;
}
};
Str Add(Str x, Str y) //定义成非成员函数
{
Str z;
z.val = x.val + y.val;
return z;
}
auto operator+(Str x, Str y) //定义成非成员函数
{
Str z;
z.val = x.val + y.val;
return z;
}
int main()
{
Str x;
std::cout << x(5) << std::endl;
std::cout << x() << std::endl;
return 0;
}
● 通常来说,实现为成员函数会以 *this 作为第一个操作数(注意 == 与 <=> 的重载)
struct Str
{
int val = 3;
//auto operator+(Str x, Str y) //包含三个参数: 类的缺省的对象、x和y。Error: Overloaded 'operator+' must be a unary or binary operator (has 3 parameters)
auto operator+(Str input) //定义成成员函数,OK,包含两个参数: 类的缺省的对象、x
{
Str res;
res.val = val + input.val;
return res;
}
};
int main()
{
Str x;
Str y;
Str z = x + y; //x传值给重载+运算符的缺省参数,y传值给重载+运算符的input
std::cout << z.val << std::endl;
return 0;
}
● 根据重载特性,可以将运算符进一步划分(operator overloading - cppreference.com):
– 可重载且必须实现为成员函数的运算符( =,[],(),-> 与转型运算符)
C++标准的一个规定,无需问为什么=,[],(),-> 与转型运算符必须实现为成员函数的运算符
注意:所有可重载的运算符都可以实现为成员函数的运算符
– 可重载且可以实现为非成员函数的运算符
除了 =,[],(),-> 与转型运算符,其他的运算符一定程度上(一些情况下)可以实现为非成员函数的运算符
– 可重载但不建议重载的运算符( &&, ||, 逗号运算符)
● C++17 中规定了相应的求值顺序但没有方式实现短路逻辑
– 不可重载的运算符(如 ? :运算符)
参考
深蓝学院:C++基础与深度解析
operator overloading