Detailed explanation of C++11 operator overloading and examples of vector class overloading (<<, >, +, -, * etc.)

Posted by ipwnzphp on Tue, 18 Jan 2022 19:17:35 +0100

1. Introduction to C + + operator overloading

The operands of predefined operators in C + + can only be basic data types. But in fact, similar operations are required for many user-defined types (such as classes). At this time, we must redefine these operators in C + + and give new functions to the existing operators, so that they can be used for specific types to perform specific operations. The essence of operator overloading is function overloading. It provides the scalability of C + +, and it is also one of the most attractive features of C + +.

The following rules should be followed when overloading operators:

(1) except the generic relational operator "." All operators in C + + can be overloaded except the member pointer operator '. *', scope operator '::', sizeof operator and ternary operator '?:'.

(2) overloaded operators are limited to those allowed to be overloaded within the scope of existing operators in C + + language, and new operators cannot be created.

(3) operator overloading is essentially function overloading. Therefore, the compiler shall follow the selection principle of function overloading.

(4) the overloaded operator cannot change the priority and associativity of the operator, nor the number and syntax structure of operator operands.

(5) operator overloading cannot change the meaning of the operator used for internal type objects. It can only be used with user-defined type objects, or when user-defined type objects and internal type objects are mixed.

(6) operator overloading is an appropriate transformation of the original operator according to the actual needs of new type data. The overloaded function should be similar to the original function to avoid using overloaded operator without destination.

1.1 monocular and binocular operators

(1) when the binocular operator is overloaded as a member function of a class, the function explicitly describes only one parameter, which is the right operand of the operator.

For example, if you overload the + sign, if it is written outside the class, you need two parameters, but if it is written inside the class, you can only write one parameter, because when this function is called, it will automatically pass in a this pointer, which is the object itself, so you only need one parameter

(2) when the preceding unary operator is overloaded as a member function of a class, there is no need to explicitly specify parameters, that is, the function has no formal parameters.

(3) when the post unary operator is overloaded as a member function of a class, the function must take an integer formal parameter.

For example, pre + +, and post + +, with an integer parameter is just to distinguish

1.2 friend operator

Some operators must be declared as friends, such as < <, > > operators

Because =, + operators are the most basic operators in c + +, and > >, < < operators are written in a class in the standard header file. You cannot declare this function as a function of your custom class, because it is a function in other classes, so you can only declare it as a friend function after declaring it as a friend function, Then this function can access the private member variables in your custom class

2. Example explanation

Just looking at these concepts, I think the heads of students who have not been in contact with them are big. Next, I will explain how to use each operator overload through an example of a vector class

2.1 header file definition

This time, let's take an example of a vector class. What is a vector class? It's a vector in mathematics, a bracket and two numbers in it. You can see it by looking at the header file

class Vec2D {
private:
	double x_;
	double y_;

public:

	static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
	Vec2D(double x, double y) :x_(x), y_(y) {}
	Vec2D() { x_ = 0.0; y_ = 0.0; }
	
	std::string toString();
	
	friend Vec2D operator+(const Vec2D& v1, const Vec2D& v2);
	friend Vec2D operator-(const Vec2D& v1, const Vec2D& v2);
	friend double operator*(const Vec2D& v1, const Vec2D& v2);
	friend Vec2D operator+(const Vec2D& v1, double num);
	friend Vec2D operator*(const double num, const Vec2D& v2);
	friend Vec2D operator*(const Vec2D& v2, const double num);
	friend istream& operator>>(istream& stream, Vec2D& v1);
	friend std::ostream& operator<<(std::ostream& stream, const Vec2D& v1);

	Vec2D negative();

	Vec2D operator-();

	Vec2D operator++();
	Vec2D operator++(int dummy);

	Vec2D operator--();

	Vec2D operator+=(const Vec2D& v);
	Vec2D operator-=(const Vec2D& v);

	double& operator[](const int& index);

	double magnitude();
	double direction();
	int compareTo(Vec2D& v2);

	operator double();

	double getX()const { return x_; }
	double getY() const { return y_; }
	void setX(double x) { x_ = x; }
	void setY(double y) { y_ = y; }
};

As you can see, the private member is x_ And y_, Then I overloaded many functions. Let's take a look at the specific implementation

2.2 implementing operator overloading

toString function

I won't say more about this function. It's relatively simple

std::string Vec2D::toString()
{
	std::string res = "(" + std::to_string(getX()) + ", " + std::to_string(getY()) + ")";
	return res;
}

negative function

This function is used to make the vector negative

Vec2D Vec2D::negative()
{
	return Vec2D(-1 * x_, -1 * y_);
}

operator function

The first overloaded function appears, which is the overloaded symbol, which makes it more convenient to change the vector to the negative direction
In this way, we can call it in the form of - a,-b

Vec2D Vec2D::operator-()
{
	return Vec2D(-1 * x_, -1 * y_);
}

operator + + function

This function is the leading + + operator. Returning * this means returning the current object

Vec2D Vec2D::operator++()
{
	x_++;
	y_++;
	return *this;
}

operator + + function

This function is a post + + operator, so a type parameter is added after it. This parameter only means to distinguish it from the pre + + operator
We first create a temporary variable, and then add 1 to X and y, but the temporary variable is returned. In this way, the post + + operation is realized

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D Vec2D::operator++(int dummy)
{
	Vec2D ret(x_, y_);
	x_++;
	y_++;
	return ret;
}

operator – function

Subtraction, similarly, is to subtract X and y by 1

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D Vec2D::operator--()
{
	x_ -= 1;
	y_ -= 1;
	return *this;
}

operator + =, - = function

These two functions are similar. I'll talk about them together. Here is to add or subtract the object calling the function itself from v in the parameter

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D Vec2D::operator+=(const Vec2D& v)
{
	x_ += v.x_;
	y_ += v.y_;
	return *this;
}

Vec2D Vec2D::operator-=(const Vec2D& v)
{
	x_ -= v.x_;
	y_ -= v.y_;
	return *this;
}

operator [] function

[] is overloaded here. There is a parameter, index, which is used to select whether to return x or y

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
double& Vec2D::operator[](const int& index)
{
	if (index == 0) {
		return x_;
	}
	else if (index == 1) {
		return y_;
	}
	else {
		printf("subscript error\n");
		exit(0);
	}
}

operator + (out of class) function

Because it is overloaded outside the class, it has two parameters. At the same time, pay attention to declaring this function as a friend function, because it can access private member variables

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
//Out of class overloading, operator overloading functions as friend functions of the class
Vec2D operator+(const Vec2D& v1, const Vec2D& v2) {
	Vec2D ret;

	ret.setX(v1.getX() + v2.getX());
	ret.setY(v1.getY() + v2.getY());

	return ret;
}

Vec2D operator+(const Vec2D& v1, double num) {
	Vec2D ret;

	ret.setX(v1.getX() + num);
	ret.setY(v1.getY() + num);

	return ret;
}

operator * function

Here * is overloaded to multiply vectors

static string AuthorBlog = "https://www.cnblogs.com/wanghongyang";
Vec2D operator*(const double num, const Vec2D& v2) {
	Vec2D ret;

	ret.setX(num * v2.getX());
	ret.setY(num * v2.getY());

	return ret;
}

Reload > ><<

Here is a hole to avoid. You must introduce iostream header files instead of using
These two functions are used to implement cout and cin
As you can see, the implementation of cin is implemented through the istream object
cout is implemented through ostream
Remember to return the istream or ostream object at the end

istream& operator>>(istream& stream, Vec2D& v1)
{
	double x, y;
	stream >> x >> y;
	v1.setX(x);
	v1.setY(y);
	// You can also directly
	// stream >> x_ >> y_;
	return stream;
}

ostream& operator<<(ostream& stream, const Vec2D& v1)
{
	std::string res = "(" + std::to_string(v1.getX()) + ", " + std::to_string(v1.getY()) + ")";
	stream << res;

	return stream;
}

Topics: C++