Symmetric and Commutative Operators in C++
💡💡 Have you ever pondered upon the distinctions between 𝗼𝘃𝗲𝗿𝗹𝗼𝗮𝗱𝗶𝗻𝗴 an 𝗼𝗽𝗲𝗿𝗮𝘁𝗼𝗿 in a C++ class 𝗮𝘀 𝗮 𝗺𝗲𝗺𝗯𝗲𝗿 𝗳𝘂𝗻𝗰𝘁𝗶𝗼𝗻 𝗢𝗥 𝗮𝘀 𝗮𝗻 𝗲𝘅𝘁𝗲𝗿𝗻𝗮𝗹 𝗳𝘂𝗻𝗰𝘁𝗶𝗼𝗻?
In C++, it’s immensely beneficial to be able to overload operators for custom data types defined as classes. However, we may have concerns about whether to implement it as a member function or as an external function. Here are some 𝗰𝗿𝘂𝗰𝗶𝗮𝗹 𝗽𝗼𝗶𝗻𝘁𝘀 to 𝗰𝗼𝗻𝘀𝗶𝗱𝗲𝗿 𝗯𝗲𝗳𝗼𝗿𝗲 𝗺𝗮𝗸𝗶𝗻𝗴 a 𝗱𝗲𝗰𝗶𝘀𝗶𝗼𝗻.
💭💭 Let's consider a scenario where we have a class C with a conversion constructor from int to C type, and an overloaded member function operator+ (C). We also have two C objects: C result{}; and C c{}; and an int variable int x;. If we try to write "𝗿𝗲𝘀𝘂𝗹𝘁 = 𝗰 + 𝘅;", the first parameter is implicitly received, while the second parameter is explicitly passed as a formal parameter of the method. Therefore, the compiler interprets the instruction as "𝗿𝗲𝘀𝘂𝗹𝘁 = 𝗰.𝗼𝗽𝗲𝗿𝗮𝘁𝗼𝗿+(𝘅);", implicitly converting the integer x to a data type of C using the conversion constructor defined in our class C.
However, if we try to do "𝗿𝗲𝘀𝘂𝗹𝘁 = 𝘅 + 𝗰;", the compiler would throw an error, as it'd interpret it as "𝗿𝗲𝘀𝘂𝗹𝘁 = 𝘅.𝗼𝗽𝗲𝗿𝗮𝘁𝗼𝗿+(𝗰);", and it’s impossible to implicitly convert the parameter x from an integer to type C because in this case, x is not an explicit parameter but an implicit one. This brings us to a fundamental rule in C++:
⛔
The compiler does not perform implicit conversions on implicit parameters.
⛔
🤔🤔 At this point, you might be wondering: "What if we define our operator+() as an external function?" If operator+() is defined as an external function, it would receive explicit parameters, allowing for implicit conversion of all parameters. However, this approach lacks encapsulation and does not provide access to private attributes.
Recommended by LinkedIn
⚙️⚙️ Another option to consider when overloading operators in C++ is to implement them as friend functions. Friend functions do not receive implicit parameters, which allows for control over implicit conversion. This approach may not fully adhere to the principle of encapsulation as it defines the operator as an external function. Nevertheless, it provides the advantage of accessing private attributes from the friend operator, which is not possible when defining operators as external functions without being friends.
🔥🔥 Conclusion
External Function Example
Member Function Example