3-d vectors with operator overloading ===================================== This example extends the previous 3-d vector project by introducing operator overloading. The Vector_3d class and most of the underlying vector operations are essentially unchanged. Refer to the previous project for details about 3-dimensional vectors, inner products, norms, projections, cross products, normalization, const references, and the organization of the class into header and source files. The focus of this project is on allowing familiar C++ operators to work with Vector_3d objects. Operator overloading ==================== In the previous project, operations on vectors were performed using ordinary functions. For example, add( u, v ) sub( u, v ) mul( 3.0, u ) equal( u, v ) With operator overloading, these operations can instead be written as u + v u - v 3.0*u u == v For example, when the compiler encounters u + v for two Vector_3d objects, it can use the overloaded function operator+( u, v ) Thus, operator overloading allows operations on objects to be written using notation that more closely resembles the corresponding mathematical notation. Operator overloading does not create new operators, nor does it change the precedence or associativity of existing operators. It defines what an existing operator does when applied to particular types. Overloaded arithmetic operators =============================== This project overloads the binary operators u + v u - v a*u u*a u/a where u and v are Vector_3d objects and a is a scalar. Two overloads of operator* are required to support both a*u and u*a because these expressions pass their arguments to operator* in different orders. C++ does not infer from mathematics that scalar multiplication is commutative. There is no overload for a/u because division of a scalar by a vector is not defined. Unary and binary operators ========================== The + and - operators can be either unary or binary. The expressions +u -u each have one operand and therefore use the unary versions of operator+ and operator-. The expressions u + v u - v each have two operands and therefore use the binary versions. These are examples of function overloading: the functions have the same identifier but different parameter lists. Reusing overloaded operators ============================ Once fundamental operators have been defined, other operators can often be implemented using them. For example, this project implements operations using expressions such as a*u (-1.0)*u u + (-v) (1.0/a)*u !(u == v) This avoids unnecessarily repeating the component-by-component calculations and makes the relationships between the operations clearer. Comparison operators ==================== The operators u == v u != v are overloaded to compare two Vector_3d objects. Two vectors are considered equal when all three corresponding components are equal. The != operator is then implemented using the already defined == operator. Compound assignment operators ============================= This project also overloads the compound assignment operators u += v u -= v u *= a u /= a Unlike expressions such as u + v these operations modify their left operand. Each compound assignment operator returns the modified Vector_3d object by reference. This is consistent with the behavior of the corresponding built-in C++ operators and allows the result of the operation to be used in another expression. Output using operator<< ======================= The stream insertion operator << is overloaded so that a Vector_3d object can be sent directly to an output stream: std::cout << u; The overload has the form std::ostream &operator<<( std::ostream &out, Vector_3d const &u ); The output stream is returned by reference. This allows another insertion to immediately operate on the same stream, making expressions such as std::cout << u << v << std::endl; possible. This is the same general mechanism that allows std::cout to output built-in values such as integers and floating-point numbers. Operations that remain ordinary functions ========================================= Not every operation should be represented by an operator. Functions such as inner( u, v ) norm( u ) proj( u, v ) cross( u, v ) normalize( u ) remain ordinary functions because C++ does not provide existing operators that naturally represent these operations. Operator overloading should make code clearer and more natural; it should not assign surprising meanings to unrelated operators. Files ===== Vector_3d.hpp Contains the Vector_3d class definition and the declarations of the ordinary functions and overloaded operators. Vector_3d.cpp Contains the definitions of the functions and overloaded operators. main.cpp Demonstrates the overloaded arithmetic, unary, comparison, compound assignment, and stream insertion operators. For additional details about the Vector_3d class and the underlying vector operations, refer to the previous 3-d vector project. Compiling ========= Compile both main.cpp and Vector_3d.cpp. For example: g++ -std=c++17 -Wall -Wextra -pedantic main.cpp Vector_3d.cpp