In C++, I can change the operator on a specific class by doing something like this:
MyClass::operator==/*Or some other operator such as =, >, etc.*/(Const MyClass rhs) {
/* Do Stuff*/;
}
But with there being no classes (built in by default) in C. So, how could I do operator overloading for just general functions?
For example, if I remember correctly, importing stdlib.h gives you the -> operator, which is just syntactic sugar for (*strcut_name).struct_element.
So how can I do this in C?
Thank you.
Plain old C does not have operator overloading in any form. The -> "operator" to access a member of a pointer is standard C and is not introduced by any header file.
Built-in operators in C language are overloaded. The fact that you can use binary + to sum integers, floating-point numbers and perform pointer arithmetic is a canonical example of operator overloading.
However, C offers no features for user-level operator overloading. You can't define your own operators in C.
The -> structure pointer dereferencing operator is part of the C spec. stdlib.h does not affect this.
Sure, you can't overload operators in C.
The -> operator is part of the C language, no #include needed.
Related
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Operator overloading
I was wonder how can I over load the Conditional operator in cpp?
int a,b,c;
a=10;
b=11;
c = (a>b) ? a : b;
Is it possible?
You cannot overload the conditional operator.
Several operators cannot be overloaded. These operators take a name, rather than an object, as their right operand:
Direct member access (.)
Deference pointer to class member (.*)
Scope resolution (::)
Size of (sizeof)
The conditional operator (?:) also cannot be overloaded.
Additionally, the new typecast operators: static_cast<>, dynamic_cast<>, reinterpret_cast<>, and const_cast<>, and the # and ## preprocessor tokens cannot be overloaded.
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=23
No, you can't overload the conditional operator, since it's simply shorthand for a simple if..else block.
You can however overload the operators used in the condition, but not for primitive types such as int, like you have in your example above.
I was looking at the C++ standard regarding member reference operators (the unary * dereferencing operator, the -> member accessor operator) as well as many other related questions:
C++ - Difference between (*). and ->?
ptr->hello(); /* VERSUS */ (*ptr).hello();
C++ pointers difference between * and ->
I saw that most answers stated that p->m is syntactic sugar for (*p).m as defined by the C++ Standard (5.2.5, paragraph 2):
The expression E1->E2 is converted to the equivalent form (*(E1)).E2
Many comments also noted that because operator* and operator-> are overloadable in classes, they should be overloaded uniformly to ensure consistent behavior.
These statements seem to contradict each other: if (as per the standard) E1->E2 is converted to the equivalent form (*(E1)).E2, then what would be the purpose of overloading operator-> (as is permitted by the standard)?
Simpler stated, are these two parts of the standard in conflict, or am I misunderstanding the Standard?
Does the E1->E2 equivalence transformation to (*(E1)).E2 apply to all complete types or only to built in ones?
The conversion from E1 -> E2 to (*(E1)).E2 only applies to raw pointer types. For class types, E1 -> E2 evaluates to (E1).operator->().E2, which potentially might recursively expand out even more copies of operator-> if the return type of operator-> is not itself a pointer type. You can see this by creating a type that supports operator* but not operator-> and trying to use the arrow operator on it; you'll get an error that operator-> is undefined.
As a follow-up, it's common to implement operator -> in terms of operator * in a way that makes the semantics of -> match the semantics for pointers. You often see things like this:
PointerType ClassType::operator-> () const {
return &**this;
}
This expression is interpreted as
&(*(*this)),
meaning "take this object (*this), dereference it (*(*this)), and get the address of what you find (&(*(*this)).)." Now, if you use the rule that E1 -> E2 should be equivalent to (*(E1)).E2, you can see that you end up getting something equivalent.
Every programmer should know that:
(De Morgan's Laws)
Under some circumstances, in order to optimize the program, it may happen that compiler modifies (!p && !q) to (!(p || q)).
The two expressions are equivalent, and it makes no difference evaluating the first or the second.
But in C++ it is possible to overload operators, and the overloaded operator may not always respect this property. So transforming the code this way will actually modify the code.
Should the compiler use De Morgan's Laws when !, || and && are overloaded?
Note that:
Builtin operators && and || perform short-circuit evaluation (do not evaluate the second operand if the result is known after evaluating the first), but overloaded operators behave like regular function calls and always evaluate both operands.
...
Because the short-circuiting properties of operator&& and operator|| do not apply to overloads, and because types with boolean semantics are uncommon, only two standard library classes overload these operators ...
Source: http://en.cppreference.com/w/cpp/language/operator_logical
(emphasis mine)
And that:
If there is a user-written candidate with the same name
and parameter types as a built-in candidate operator function, the built-in operator function is hidden and
is not included in the set of candidate functions.
Source: n4431 13.6 Built-in operators [over.built] (emphasis mine)
To summarize: overloaded operators behave like regular, user-written functions.
NO, the compiler will not replace a call of a user-written function with a call of another user-written function.
Doing otherwise would potentially violate the "as if" rule.
I think that you have answered your own question: no, a compiler can not do this. Not only the operators can be overloaded, some can not be even defined. For example, you can have operator && and operator ! defined, and operator || not defined at all.
Note that there are many other laws that the compiler can not follow. For example, it can not change p||q to q||p, as well as x+y to y+x.
(All of the above applies to overloaded operators, as this is what the question asks for.)
No, in that case the transformation would be invalid. The permission to transform !p && !q into !(p || q) is implicit, by the as-if rule. The as-if rule allows any transformation that, roughly speaking, cannot be observed by a correct program. When overloaded operators are used and would detect the transformation, that automatically means the transformation is no longer allowed.
Overloaded operators per se are just syntactic sugar for function calls; the compiler itself is not allowed to make any assumption about the properties that may or may not hold for such calls. Optimizations that exploit properties of some specific operator (say, De Morgan's for boolean operators, commutativity for sums, distributivity for sum/product, transformation of integral division in an appropriate multiplication, ...) can be employed only when the "real operators" are used.
Notice instead that some parts of the standard library may associate some specific semantic meaning to overloaded operators - for example, std::sort by default expects an operator< that complies to a strict weak ordering between the elements - but this is of course listed in the prerequisites of each algorithm/container.
(incidentally, overloading && and || should probably be avoided anyway since they lose their short-circuiting properties when overloaded, so their behavior becomes surprising and thus potentially dangerous)
You are asking whether the compiler can arbitrarily rewrite your program to do something you did not write it to do.
The answer is: of course not!
Where De Morgan's laws apply, they may be applied.
Where they don't, they may not.
It's really that simple.
Not directly.
If p and q are expressions so that p does not have overloaded operators, short circuit evaluation is in effect: expression q is going to be evaluated only if p is false.
If p is of non-primitive type, there is no short circuit evaluation and overloaded function could be anything - even not related to the conventional usage.
Compiler will do its optimizations in its own way. Perhaps it might result de Morgan identities, but not on the level of if condition replacement.
DeMorgan's laws apply to the semantics of those operators. Overloading applies to the syntax of those operators. There is no guarantee that an overloaded operator implements the semantics that are needed for DeMorgan's laws to apply.
But in C++ it is possible to overload operators, and the overloaded operator may not always respect this property.
Overloaded operator is no longer an operator, it is a function call.
class Boolean
{
bool value;
..
Boolean operator||(const Boolean& b)
{
Boolean c;
c.value = this->value || b.value;
return c;
}
Boolean logical_or(const Boolean& b)
{
Boolean c;
c.value = this->value || b.value;
return c;
}
}
So this line of code
Boolean a (true);
Boolean b (false);
Boolean c = a || b;
is equivalent to this
Boolean c = a.logical_or(b);
Can we declare a function like this in c++:
int operator + (int , int);
Your answers will be appreciated!
Thanks
You cannot redefine a built-in operator. Operator overloading
is designed to allow you to extend the language, not to change
it. At least one of the parameters of an overloaded operator
must be a user defined type (class or enum type) or a reference
to a user defined type.
Yes: You can pass ints and floats into overloaded functions
No: You cannot overload/override the operators for built in types when the built-in types are on both sides of the expression.
No we cannot overload integer or float types because overloading means to change the working of existing operators or make them to work with objects int is single member not an object.
While trying to learning operator overloading, I read the following statements from C++ Primer. Frankly speaking, I do not quite understand what does the message that these statements want to deliver. The examples include defining both member binary operator and nonmember binary operator. Is there any difference when using them?
Ordinarily we define the arithmetic and relational operators as nonmember functions and we define assignment operators as members:
Sales_item& Sales_item:: operator (const Sales_item&)
Sales_item operator_(const Sales_item&, const Sales_item&);
Both addition and compound assignment are binary operators, yet these functions define a different number of parameters. The reason for the discrepancy is the this pointer.
Yes, there is a difference in actual use. In particular, when you overload an operator as a non-member function, conversions can be applied to either operand (or both operands). When you overload a binary operator with a member function, conversions can only be applied to the right operand.
This can lead to some oddities. For example, consider writing a "bignum" package and you wanted to overload operator+ to handle bignums. If you overload it as a member function, you get an oddity like this:
int x = 2;
bignum y = 3;
bignum z;
z = y + x; // works fine.
z = x + y; // doesn't work: x isn't a bignum, and can/won't be converted to one
If, instead, you overload operator+ using a non-member function, both of the operations will work (presuming you have a constructor to create a bignum from an int, which you'd almost certainly want).
A few operators (particularly assignment operators, such as =, +=, -=, etc.) are special. A conversion creates a temporary object, and assigning to a temporary object 1) isn't allowed, and 2) wouldn't make sense or accomplish much anyway. Therefore, when you're overloading assignment operators, you always use a member function.