Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

The operators obviously return a bool, indicating true or false for the corresponding operation.

All of the operators take their arguments by const&, because the only thing that does operators do is compare, so they shouldn't modify the objects. Passing by & (reference) is faster than by value, and to make sure that the operators don't modify it, it is a const-reference.

Note that the operators inside the class/struct are defined as const, the reason for this is that without the functions being const, comparing const objects would not be possible, as the compiler doesn't know that the operators don't modify anything.

Section 36.8: Assignment operator

The assignment operator is one of the most important operators because it allows you to change the status of a variable.

If you do not overload the assignment operator for your class/struct, it is automatically generated by the compiler: the automatically-generated assignment operator performs a "memberwise assignment", ie by invoking assignment operators on all members, so that one object is copied to the other, a member at time. The assignment operator should be overloaded when the simple memberwise assignment is not suitable for your class/struct, for example if you need to perform a deep copy of an object.

Overloading the assignment operator = is easy, but you should follow some simple steps.

1. Test for self-assignment. This check is important for two reasons:

a self-assignment is a needless copy, so it does not make sense to perform it; the next step will not work in the case of a self-assignment.

2.Clean the old data. The old data must be replaced with new ones. Now, you can understand the second reason of the previous step: if the content of the object was destroyed, a self-assignment will fail to perform the copy.

3.Copy all members. If you overload the assignment operator for your class or your struct, it is not

automatically generated by the compiler, so you will need to take charge of copying all members from the other object.

4. Return *this. The operator returns by itself by reference, because it allows chaining (i.e. int b = (a = 6) + 4; //b == 10).

//T is some type

T& operator=(const T& other)

{

//Do something (like copying values) return *this;

}

Note: other is passed by const&, because the object being assigned should not be changed, and passing by reference is faster than by value, and to make sure than operator= doesn't modify it accidentally, it is const.

The assignment operator can only to be overloaded in the class/struct, because the left value of = is always the class/struct itself. Defining it as a free function doesn't have this guarantee, and is disallowed because of that.

When you declare it in the class/struct, the left value is implicitly the class/struct itself, so there is no problem with that.

GoalKicker.com – C++ Notes for Professionals

210

Section 36.9: Function call operator

You can overload the function call operator ():

Overloading must be done inside of a class/struct:

//R -> Return type

//Types -> any different type

R operator()(Type name, Type2 name2, ...)

{

//Do something //return something

}

//Use it like this (R is return type, a and b are variables) R foo = object(a, b, ...);

For example:

struct Sum

{

int operator()(int a, int b)

{

return a + b;

}

};

//Create instance of struct Sum sum;

int result = sum(1, 1); //result == 2

Section 36.10: Bitwise NOT operator

Overloading the bitwise NOT (~) is fairly simple. Scroll down for explanation

Overloading outside of class/struct:

T operator~(T lhs)

{

//Do operation return lhs;

}

Overloading inside of class/struct:

T operator~()

{

T t(*this); //Do operation return t;

}

Note: operator~ returns by value, because it has to return a new value (the modified value), and not a reference to the value (it would be a reference to the temporary object, which would have garbage value in it as soon as the operator is done). Not const either because the calling code should be able to modify it afterwards (i.e. int a = ~a + 1; should be possible).

GoalKicker.com – C++ Notes for Professionals

211

Inside the class/struct you have to make a temporary object, because you can't modify this, as it would modify the original object, which shouldn't be the case.

Section 36.11: Bit shift operators for I/O

The operators << and >> are commonly used as "write" and "read" operators:

std::ostream overloads << to write variables to the underlying stream (example: std::cout)

std::istream overloads >> to read from the underlying stream to a variable (example: std::cin)

The way they do this is similar if you wanted to overload them "normally" outside of the class/struct, except that specifying the arguments are not of the same type:

Return type is the stream you want to overload from (for example, std::ostream) passed by reference, to allow chaining (Chaining: std::cout << a << b;). Example: std::ostream&

lhs would be the same as the return type

rhs is the type you want to allow overloading from (i.e. T), passed by const& instead of value for performance reason (rhs shouldn't be changed anyway). Example: const Vector&.

Example:

//Overload std::ostream operator<< to allow output from Vector's std::ostream& operator<<(std::ostream& lhs, const Vector& rhs)

{

lhs << "x: " << rhs.x << " y: " << rhs.y << " z: " << rhs.z << '\n'; return lhs;

}

Vector v = { 1, 2, 3};

//Now you can do std::cout << v;

GoalKicker.com – C++ Notes for Professionals

212