c++面向对象——运算符重载
运算符重载c运算符c中的运算符可以分为单目、二目、三目运算符。单目运算符只有一个操作数二目运算符有两个操作数三目运算符有三个操作数。也可叫做一元、二元、三元运算符。单目运算符a a a-- --a !a ~a a -a a *a static_castT(a)new a delete a delete[] asizeof a二目运算符o-a o(a) o[a] a * b a / b a b a - b a % b a b a ba b a b a b a b a b a ! b a b a | b a ^ ba b a || b a b a b a - b a * b a / b a % b a ba b a b a | b a ^ b new T[a]a, bn::ao.a三目运算符a ? b : c对于内建类型运算符是在c语言中定义好的。自定义类型想要使用运算符往往需要进行运算符重载。其中背景灰色的运算符例子是无法重载的。自定义类型运算符重载对于c内建类型int可以直接使用运算符int a 5; int b a 4;自定义类型如果想要使用运算符往往需要进行运算符重载//复数类型 Complex c1 (5, 6); Complex c2 c1 4; ↓ Complex::operator (int) //√ int::operator (int) //×对于自定义类型使用运算符本质是调用自定义类型的一个函数。函数名是以 operator 运算符 表示的。自定义类型的运算符重载本质是函数重载。使用运算符时本质是使用对应运算符函数的语法糖。对于自定义类型这种函数是为了使其支持运算符重载而内建类型并不存在这种函数。二元运算符例自定义一个类表示虚数在类中使用 operator 重载运算符。class Complex { public: Complex(int real, int image); Complex operator (const Complex c) const; Complex operator (int r) const; void ShowComplex() const; private: int r_, i_; }; Complex::Complex(int real, int image) :r_(real), i_(image) {}; Complex Complex::operator (const Complex c) const { return Complex(r_ c.r_, i_ c.i_); }; Complex Complex::operator (int r) const { return Complex(r_ r, i_); } void Complex::ShowComplex() const{ std::cout r_ _ i_ std::endl; } int main() { Complex complex1(5, 6); Complex complex2 complex1 4; Complex complex3 complex2 complex1; Complex complex4 complex1.operator(complex2); complex1.ShowComplex(); complex2.ShowComplex(); complex3.ShowComplex(); complex4.ShowComplex(); }使用operator 定义一个虚数 虚数的函数。返回值为 Complex类型参数代表号右边的操作数而号左边的操作数默认为operator 所在的自定义类型。由于 运算 不改变所使用的两个操作数用const修饰表示只读。括号内的const修饰括号中的参数而后面的const修饰函数本身表示operator所在的自定义类型只读可以理解为this是只读的。函数中直接在return时使用构造函数返回一个 Complex类型。Complex Complex::operator (const Complex c) const { return Complex(r_ c.r_, i_ c.i_); };同样也可以将参数定义为 int类型 重载运算符这样可以在 号 右边直接加上 int类型 的数据。Complex Complex::operator (int r) const { return Complex(r_ r, i_); }运算符重载本质是函数重载使用 运算符等价于直接使用函数。Complex complex4 complex1.operator(complex2);上面的代码运行结果为5_6 9_6 14_12 14_12如果自定义类型是已经封装好的或者左操作数不是自定义类型也可以在自定义类型外声明运算符重载。不过这样的外部函数无法调用类中被声明为private的私有属性可以将外部函数声明为友元来解决。class Complex { public: Complex(int real, int image); friend Complex operator (const Complex c1, const Complex c2); friend Complex operator (int r, const Complex c); void ShowComplex(); private: int r_, i_; }; Complex operator (const Complex c1, const Complex c2) { return Complex(c1.r_ c2.r_, c1.i_ c2.i_); } Complex operator (int r, const Complex c) { return Complex(r c.r_, c.i_); }一元运算符例//一元运算符重载 class Complex { public: Complex(int real, int image); //取负数运算符重载 Complex operator-() const; //自增运算符重载 Complex operator(); //后置自增运算符重载 Complex operator(int); void ShowComplex() const; private: int r_, i_; }; Complex::Complex(int real 0, int image 0) :r_(real), i_(image) { }; Complex Complex::operator-() const { return Complex(-r_, -i_); }; //全局运算符重载 //Complex operator-(const Complex c) { // return Complex(-c.r_, -c.i_); //} Complex Complex::operator() { r_; i_; return *this; } Complex Complex::operator(int) { Complex temp(*this); //保存自增前的值 r_; i_; return temp; } void Complex::ShowComplex() const { std::cout r_ _ i_ std::endl; } int main() { Complex complex1(5, 6); Complex complex2 -complex1; //Complex complex2 operator-(complex1); complex1.ShowComplex(); complex2.ShowComplex(); std::cout 自增运算符重载 std::endl; complex1; complex1.ShowComplex(); Complex complex3 complex1; complex3.ShowComplex(); complex1.ShowComplex(); std::cout 后置自增运算符重载 std::endl; Complex complex4 complex1; complex4.ShowComplex(); complex1.ShowComplex(); }在一元运算符中可以定义比如取负数的运算符。需要注意自增和后置自增在使用时返回值有所不同。使用 operator() 表示自增operator(int) 表示后置自增看起来像是二目运算符重载不过int可以认为无意义只是为了区分前置后置自增。在前置自增中返回的值经过了自增操作在后置自增中返回值发送后再进行自增可以使用一个寄存变量保存自增前的值最后返回这个寄存变量的值。Complex Complex::operator() { r_; i_; return *this; } Complex Complex::operator(int) { Complex temp(*this); //保存自增前的值 r_; i_; return temp; }如果要用函数表示后置自增可以这样表示。其中0对应的是参数中的int没有实际意义。Complex complex5 complex1.operator(0);重载括号运算符//重载()运算符 //函数对象Functor是一个重载了operator()运算符的类的对象。它可以像函数一样被调用并且可以携带状态。 struct Invoker { int arg_; int (*func)(int, int); int operator() (int a) { return func(arg_, a); } }; int f(int a, int b) { return a b; } int main() { Invoker invoker{ 10, f }; int result invoker(5); // 调用operator()相当于f(10, 5) std::cout Result: result std::endl; // 输出结果 return 0; }() 也可以在类或结构体中被重载。重载了 () 的对象称作函数对象因为在对象后加 () 可以直接使用重载的 ()运算符这使得对象可以像函数一样被调用所以叫做函数对象。函数对象的一个好处是可以携带状态。