在C++中,operator关键字将声明一个用于指定operator-symbol含义的函数。这将为运算符提供多个含义,或者将”重载”它。编译器通过检查其操作数类型来区分运算符不同的含义。你可以在全局或为各个类重新定义大多数内置运算符的函数。重载运算符作为函数来实现。
操作符重载的实现方式:通过”友元函数”、全局函数、类成员函数。
要实现操作符重载就要使用操作符重载函数,操作符重载函数用关键字operator实现。操作符重载函数是一个函数,只不过这个函数的函数名为operator再加上后面要重载的操作符而已。
当操作符重载函数作为类的成员函数时,操作符重载函数的参数会比作为友元或者全局函数的操作符重载函数少一个参数,因为操作符重载类成员函数把调用该函数的对象作为函数的第一个参数,也就是隐含的this指针指向调用该函数的第一个对象,所以会少一个参数。
一般来说操作符重载函数一般不要求作为类的成员函数或者是友元函数,一般情况下可以将操作符重载函数作为类的成员函数。但是有一种情况必须要求操作符函数作为类的友元函数或者是全局函数,就是一个内置类型和对象相加的情况。
必须把它作为类成员函数的运算符有:(),[],->;和任何赋值运算符,重载这些运算符时必须把操作符函数声明为类的成员函数。
利用友元函数重载二元操作符时,形式参数是两个,而利用类成员函数时,形式参数却只有一个。这是因为类成员函数中存在this指针,这相当于一个参数,所以类成员实现操作符重载需要的形式参数比原来少一个。
运算符重载的原则:
(1)、C++中只能对已有的C++运算符进行重载,不允许用户自己定义新的运算符;
(2)、C++中绝大部分的运算符可重载,除了成员访问运算符.,作用域运算符::,长度运算符sizeof以及条件运算符?:;
(3)、运算符重载后不能改变运算符的操作对象(操作数)的个数;
(4)、重载不能改变运算符原有的优先级和原有的结合性;
(5)、运算符重载不能全部是C++中预定义的基本数据,这样做的目的是为了防止用户修改用于基本类型数据的运算符性质。
除6种操作符不能被重载外,其它均可以,不能重载的操作符包括:(1)、?: (conditional); (2)、. (member selection); (3)、.* (member selectionwith pointer-to-member); (4)、:: (scope resolution); (5)、sizeof (object sizeinformation); (6)、typeid (object type information)
测试代码如下:
operator.hpp:
#ifndef FBC_MESSY_TEST_OPERATOR_HPP_ #define FBC_MESSY_TEST_OPERATOR_HPP_ #include <istream> #include <ostream> #include <iostream> class Point { public: // various constructors Point() : x(0), y(0) {} Point(int x_, int y_) : x(x_), y(y_) {} Point(const Point& pt_) : x(pt_.x), y(pt_.y) {} // assignment operator: = Point& operator = (const Point& pt_); // compound assignment operators: += -= *= /= %= &= |= ^= <<= >>= Point& operator += (const Point& pt_); Point& operator -= (const Point& pt_); Point& operator *= (const Point& pt_); // binary arithmetic operators: + - * / % Point& operator + (const Point& pt_); Point& operator - (const Point& pt_); Point& operator * (const Point& pt_); // comparison operators: == != > < >= <= bool operator == (const Point& pt_) const; bool operator != (const Point& pt_) const; bool operator > (const Point& pt_) const; // bitwise operators: ^ | & ~ << >> // note: this function is not a member function friend std::ostream& operator << (std::ostream& out, const Point& pt_); // output // note: this function is not a member function friend std::istream& operator >> (std::istream& in, Point& pt_); // input // logical operators: ! && || //increment and decrement operators: ++ -- Point& operator ++ (); // prefix: ++ Point& operator ++ (int); // postfix: ++ public: int x, y; //< the point coordinates }; int test_operator(); #endif // FBC_MESSY_TEST_OPERATOR_HPP_operator.cpp:
#include <assert.h> #include "operator.hpp" Point& Point::operator = (const Point& pt_) { if (this == &pt_) { return *this; } this->x = pt_.x; this->y = pt_.y; return *this; } Point& Point::operator += (const Point& pt_) { this->x += pt_.x; this->y += pt_.y; return *this; } Point& Point::operator -= (const Point& pt_) { this->x -= pt_.x; this->y -= pt_.y; return *this; } Point& Point::operator *= (const Point& pt_) { this->x *= pt_.x; this->y *= pt_.y; return *this; } Point& Point::operator + (const Point& pt_) { return operator += (pt_); } Point& Point::operator - (const Point& pt_) { return operator -= (pt_); } Point& Point::operator * (const Point& pt_) { return operator *= (pt_); } bool Point::operator == (const Point& pt_) const { return (this->x == pt_.x && this->y == pt_.y); } bool Point::operator != (const Point& pt_) const { return !(operator == (pt_)); } bool Point::operator > (const Point& pt_) const { return (this->x > pt_.x && this->y > pt_.y); } std::ostream& operator << (std::ostream& out, const Point& pt_) // output { out << "x: " << pt_.x << std::endl; out << "y: " << pt_.y << std::endl; return out; } std::istream& operator >> (std::istream& in, Point& pt_) // input { std::cout << "x: "; in >> pt_.x; std::cout << std::endl; std::cout << "y: "; in >> pt_.y; std::cout << std::endl; return in; } Point& Point::operator ++ () { ++this->x; ++this->y; return *this; } Point& Point::operator ++ (int) { Point tmp(*this); operator++(); return tmp; } // note: this function is not a member function Point& operator + (const Point& pt_, int a) { Point tmp; tmp.x = pt_.x + a; tmp.y = pt_.y + a; return tmp; } int test_operator() { Point pt1; Point pt2(1, 2); Point pt0(pt2); Point pt3; pt3 = pt2; // =, same as pt3.operator=(pt2); assert(pt3.x == 1 && pt3.y == 2); Point pt4(3, 4); pt4 += pt3; assert(pt4.x == 4 && pt4.y == 6); pt4 -= pt2; assert(pt4.x == 3 && pt4.y == 4); pt4 *= pt2; assert(pt4.x == 3 && pt4.y == 8); pt4 = pt4 + pt2; assert(pt4.x == 4 && pt4.y == 10); pt4 = pt4 - pt2; assert(pt4.x == 3 && pt4.y == 8); pt4 = pt4 * pt2; assert(pt4.x == 3 && pt4.y == 16); Point pt5(3, 16); bool flag = (pt4 == pt5); assert(flag == true); flag = (pt4 != pt5); assert(flag == false); flag = (pt4 > pt2); assert(flag == true); Point pt6(4, 5); std::cout << pt4 << std::endl; // output std::cin >> pt1; // input Point pt7(4, 5); ++pt7; assert(pt7.x == 5 && pt7.y == 6); Point pt8(6, 7); pt7 = pt8++; assert(pt7.x == 6 && pt7.y == 7); int a = 10; pt7 = pt7 + a; assert(pt7.x == 16 && pt7.y == 17); return 0; }
1. http://en.cppreference.com/w/cpp/language/operators
2. https://isocpp.org/wiki/faq/operator-overloading
GitHub:https://github.com/fengbingchun/Messy_Test