Suppose we have the following class:
class Rational { // Represents rational number. n=1/2=d for example.
public:
int n = 0;
int d = 1;
};
Rational x = Rational();
x.n = 1;
x.d = 2;
Is it possible to do overloading such that 3 * x would give 3/2 instead of an error?
My teacher said that overloading happens only between objects of the same type, but why can we do overloading between cout which is of type ostream and an object of type Rational and not of the type int and Rational?
You may write for example
Rational operator *( const Rational &r, int x )
{
return { r.n * x, r.d };
}
Rational operator *( int x, const Rational &r )
{
return { r.n * x, r.d };
}
You may overload operators for user defined types. For a binary operator at least one of operands must be of a user defined type.
From the C++ 20 Standard (12.4.2.3 Operators in expressions)
2 If either operand has a type that is a class or an enumeration, a
user-defined operator function can be declared that implements this
operator or a user-defined conversion can be necessary to convert the
operand to a type that is appropriate for a built-in operator. In this
case, overload resolution is used to determine which operator function
or built-in operator is to be invoked to implement the operator.
Therefore, the operator notation is first transformed to the
equivalent function-call notation as summarized in Table 15 (where #
denotes one of the operators covered in the specified subclause).
However, the operands are sequenced in the order prescribed for the
built-in operator (7.6).
Related
In C the unary plus operator is called unary arithmetic operator and may not be applied to pointers (the C Standard, 6.5.3.3 Unary arithmetic operators).
1 The operand of the unary + or - operator shall have arithmetic
type; of the ~ operator, integer type; of the ! operator, scalar
type.
Thus this program will not compile
#include <stdio.h>
int main(void)
{
int a = 10;
int *pa = &a;
printf( "%d\n", *+pa );
return 0;
}
However in C++ the unary plus operator may be applied to pointers (the C++ Standard, 5.3.1 Unary operators)
7 The operand of the unary + operator shall have arithmetic, unscoped
enumeration, or pointer type and the result is the value of the
argument. Integral promotion is performed on integral or enumeration
operands. The type of the result is the type of the promoted operand.
And this program compiles successfully.
#include <iostream>
int main()
{
int a = 10;
int *pa = &a;
std::cout << *+pa << std::endl;
return 0;
}
What is the reason for maintaining this difference between C and C++?
The question arose when I was answering the question Why size of int pointer is different of size of int array?. I was going to show how to convert an array to a pointer in the sizeof operator.
At first I wanted to write
sizeof( +array )
However this expression is invalid in C. So I had to write
sizeof( array + 0 )
and I found that there is such a difference between C and C++.:)
Different languages may attach different semantics to the same syntax.
C and C++ are different languages with a common ancestor. C++ semantics look deceptively similar but are subtly different for some parts of the common syntax. Another curious case is this:
if (sizeof(char) == sizeof(int)) {
printf("Hello embedded world\n");
} else {
if (sizeof('a') == sizeof(char))
printf("This is C++ code\n");
if (sizeof('a') == sizeof(int))
printf("This is C code\n");
}
The reason for C++ to have extended the C syntax in the case of unary + might be to allow for some extended numeric types to be implemented as pointers, or simply for reasons of symmetry.
As Jaa-c mentions in a comment, +p is a computed expression whereas p is a reference to p. You provided another example where + can be used to force expression context. The question is why did the original authors of the C language disallow unary + on non numeric types? Maybe a side effect of the original implementation of pcc.
Note that in Javascript, the unary + operator can be applied to non number types and operates as a conversion to number.
In my considerations:
C++ is a type of Object-Oriented Language. So every data type can be treated as a "Class".
In C int is one of "the basic data type of C". But in C++ we can consider int as a Class. Thus, In C++ int pointer and int array belong to the different classes. In C a int pointer variable stored another int variable's address. int array's name instead of the first element's address of that int array. So in C they have kind of the same meaning.
As for the unary opreator "+", I understand the C++ language as: Every class In C++ represents a set of stuff. Every stuff in the set has the same properties. And there's some operations can be done onto each stuff. Of course these operations are member functions of a class. Another character In C++ is that users can overload an operator. Overload means we can do the same operation on the different Classes. For example: A man is eating a burger. we can overload action "Eat" between cats and rat: A cat is Eating a rat.
So as the C++ standard say:"The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument." That's just a overload for unary operator + in Class unscoped enumeration and pointer type. "And The Result Is The Value Of The Argument"-> I guess that's the point.
I used operator overloading for my own Bignum header, and there are some operator priority problem.
Compiler says there is some error when I do bignum+int.
(My Bignum class name is 'bignum'. Don't mind that)
Here is my class definition:
operator long long(void) const {
return atoll(num.c_str());
}
operator +(bignum b) {
//c=this+b
return c;
}
And here is the case that error happens:
bignum a(1);
int b=1;
bignum c = a+b; //this is the case
ERRORS
line 7 : IntelliSense: "+" More than one of the operators is
consistent with the operand. Built-in operators "arithmetic +
arithmetic" Function "minary::bignum::operator+(minary::bignum
b)" The operand format is minary::bignum +
int. c:\Users\Secret\Documents\Visual Studio
2013\Projects\Calculator\Calculator\Source.cpp 11 3 Calculator
Thanks in advance.
The easiest approach is to make the conversion to integers explicit: many implicit conversions cause problems anyway. Sometimes implicit conversions are useful but if you want to deal with mixed type arithmetic they tend to be more a problem than help:
class bignum {
// ...
explicit operator long long() const { ... }
// ...
};
Making the conversion operator explicit is a C++11 feature. Your class also seems to have an implicit conversion from integral types to bignum, i.e., a corresponding constructor. Prior to C++11 you could only make these constructors explicit. This may be another option to deal with the ambiguity but it would have the effect that the conversion to long long and the built-in integer addition is used. My guess that you want a bignum as a result which requires that there is no suitable conversion to an integral type.
Note that the question has nothing to do with operator priority: for any given expression the compiler determines which overloads are the best fit (roughly: require the least amount of implicit conversions). If it finds multiple equally good candidates it considers the program to be ambiguous and asks for the ambiguity to be sorted out.
While reading this article it seems that the operator + is unary. How is that.
From my understanding a unary operator is an operator that does not depend on another variable for its operation like ++a or a-- . How is the variable '+' unary. I thought it was binary ? I would appreciate it if some one could clear this up.
+ is both a unary and binary operator. The unary + form (+a) forces the operand to be evaluated as a number or a pointer, while the binary form + form (a + b) is addition.
Unary + is generally the opposite of unary -; applying it to any numeric value will not change it. (+1 == 1) However, it does have some uses, including forcing an array to decay into a pointer:
template <typename T> void foo(const T &) { }
void test() {
int a[10];
foo(a); // Calls foo<int[10]>()
foo(+a); // Calls foo<int*>()
}
(Demo)
It's the same deal with the - and * operators. You have -a (negation) and a - b (subtraction); *a (pointer dereference) and a * b (multiplication).
You overload both versions differently. For overloading via member functions:
public:
T operator+() const; // Unary
T operator+(const U &) const; // Binary
As with any other operator overload, both forms can return a value different from their enclosing type; for example you might have a string class whose operator+() returns a numeric type. This would be in line with the convention of unary + evaluating its operand as a number.
You can overload these operators as free functions, too:
T operator+(const U &); // Unary, called on type U and returns T.
T operator+(const U &, const V &); // Binary, called on types U and V and returns T.
Unary + as in +a is defined to complement unary - (-a). It is the "default" so actually not often if ever used. However it can be used with variables refering to classes, where it can be overloaded to have a class-specific meaning. So it is not quite entirely useless.
I am reading the C++ Primer, in the overloaded operation chapter, the author gave an example:
// member binary operator: left-hand operand bound to implicit this pointer
Sales_item& Sales_item::operator+=(const Sales_item&);
// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);
then, the author explained:
This difference matches the return types of these operators when applied to arithmetic types: Addition yields an rvalue and compound assignment returns a reference to the left-hand operand.
I'm not quite sure about "compound assignment returns a reference to the left-hand operand". Can anyone elaborate on that, and relevant things, please?
It means that you can do something like the following
a = 1;
(a += 1) += 1;
and the result will be a == 3. This is because the left most call to += modifies a and then
returns a reference to it. Then the next += operates on the reference to a and again adds a number to it.
On the other hand, the normal + operator returns a copy of the result, not a reference to one of the arguments. So this means that an expression such as a + a = 3; is illegal.
a = a + b;
is also
a += b;
which is equivalent to
a.operator+= (b)
operator += supports compound assignment:
(a += b) += c;
is equivalent to
a.operator+= (b).operator+= (c);
The last line would not be possible if a value was returned instead of an rvalue.
Consider the following:
c = a + b;
is also
c = a.operator+ (b);
writing
a.operator+ (b) = c;
has no effect because the value of a is not changed.
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.