Parameter Order in Operators
Does the order of parameters matter in operator overloading? Like, is (Vector3, int)
different from (int, Vector3)
?
Yes, parameter order definitely matters in operator overloading! C++ treats a * b
as a different operation from b * a
. Let's see this in action:
#include <iostream>
struct Vector3 {
float x, y, z;
};
// Vector3 * int
Vector3 operator*(const Vector3& vec, int scalar) {
std::cout << "Called Vector3 * int\n";
return Vector3{
vec.x * scalar, vec.y * scalar, vec.z * scalar
};
}
// int * Vector3
Vector3 operator*(int scalar, const Vector3& vec) {
std::cout << "Called int * Vector3\n";
return Vector3{
vec.x * scalar, vec.y * scalar, vec.z * scalar
};
}
int main() {
Vector3 vec{1.0f, 2.0f, 3.0f};
// Calls first overload
Vector3 result1{vec * 2};
// Calls second overload
Vector3 result2{2 * vec};
}
Called Vector3 * int
Called int * Vector3
This distinction is important because:
- Different parameter orders require different overloads
- The compiler looks for an exact match first
- Some operations are naturally asymmetric
For commutative operations (where order doesn't affect the result), it's common to implement one version in terms of the other:
Vector3 operator*(const Vector3& vec, int scalar) {
return Vector3{
vec.x * scalar, vec.y * scalar, vec.z * scalar
};
}
Vector3 operator*(int scalar, const Vector3& vec) {
return vec * scalar; // Reuse the other overload
}
However, for non-commutative operations like matrix multiplication or division, the order is mathematically significant and you'll want distinct implementations for each order.
Operator Overloading
This lesson introduces operator overloading, a fundamental concept to create more intuitive and readable code by customizing operators for user-defined types