Overloading postfix operator ++ - c++

I have overloaded the prefix version of operator ++. How can I overload the postfix version if the overloaded function is NOT a member of my class*?
#include <iostream>
using namespace std;
class Number{
int number;
public:
Number(int inNr):number(inNr){}
friend void operator++(Number& fst);
};
void operator++(Number& fst){
fst.number=fst.number+1;
}
int main(){
Number nr1(1);
++nr1;
//nr1++; error: no 'operator++(int)' declared for postfix '++'
}
*I understand if it is a member of the class, I can use the dummy int parameter to distinguish them.

Non-member overloads also use a dummy int parameter to distinguish them:
friend void operator++(Number&); // prefix
friend void operator++(Number&, int); // postfix
Note that some people might expect these to emulate the behaviour of the built-in operator by returning, respectively, the new and old values:
Number& operator++(Number& fst) {
fst.number=fst.number+1;
return fst; // reference to new value
}
Number operator++(Number& fst, int) {
Number old = fst;
++fst;
return old; // copy of old value
}

I believe (I can't test this out at the moment) you use the dummy int as a second parameter to the operator overload, i.e.
void operator++(Number& fst, int /*dummy*/){
fst.number=fst.number+1;
}

Related

Return type Overloading Operators

I have a questions, probably trivial...
There are restrictions on the return type with the overloading of operators?
I tried to overload operator +, in arguments I had two objects of class Nodo, and i wanted to return the sum of the attributes(with a get method), that were int.
So i write an external function int operator+(Nodo a,Nodo b) and this didn't work...So i tried with int operator+(int tot,Nod a) and this worked.
I suppose that the return type have to be one of the arguments?
class Nodo
{
private:
Nodo *Next;
Employee *Emp;
public:
Nodo(){}
Nodo(Nodo *a,Employee *b):Next(a),Emp(b){}
virtual ~Nodo(){}
void SetNext(Nodo *a){Next=a;};
Nodo* GetNext(){return Next;}
void SetEmployee(Employee *emp){Emp=emp;}
Employee* GetEmployee(){return Emp;}
};
class Employee
{
private:
string name;
int salary;
public:
Employee(string name,int salary):name(name),salary(salary){}
virtual ~Employee() {}
string GetName(){return name;}
int GetSalary(){return salary;}
virtual void PrintInfo(){cout<<"Nome "<<name<<" Salario "<<salary<<endl;}
};
I tried with
int operator+(Nodo a,Nodo b)
{
int totale;
totale=a.GetEmployee()->GetSalary()+b.GetEmployee()->GetSalary();
return totale;
}
The result is the crash.
While this work.
int operator+(int tot,Nodo a)
{
int totale;
totale=tot+a.GetEmployee()->GetSalary();
return totale;
}
There are rules for operator overloading regarding the type and number of arguments they can take.
For example:
Binary operators (such as +) declared as member functions take one
argument; if declared as global functions, they take two arguments.
Overloaded operators cannot have default arguments.
The first argument for member-function overloaded operators is always
of the class type of the object for which the operator is invoked
(the class in which the operator is declared, or a class derived from
that class). No conversions are supplied for the first argument.
But there are NO rules concerning the return type. So, you can return any type from an overloaded operator.

Pointer to member operator

I have this link http://www.codingunit.com/unary-and-binary-operator-table. It says that pointer to member operator is a binary operator.
I have this code :
class test
{
public:
int num;
test(int j)
{
num=j;
}
test* operator->()
{
this->num;
}
};
int main()
{
test T(5);
cout<<"Number is :"<<T->num;
}
As I know, non static member function of binary operator accepts one argument, but according to this program if I provide it one argument. It has an error, which says that test* operator ->(int x) should be test* operator ->(void) .
To get the expected result, you need to change your program as follows:
test* operator->()
{
return this;
}
};
int main()
{
test T(5);
cout<<"Number is :"<<T->num;
}
In your operator overloading function, you should return this pointer. Since your operator overloaded function for -> does not accept a parameter, so when you call it you don't need to pass a parameter value. So function call should be T->num;

how does this typedef syntax works..?

#include<iostream.h>
#include<conio.h>
typedef ostream& (*T)(ostream& , int);
class Base
{
T fun;
int var;
public:
Base(T func, int arg): fun(func) , var(arg)
{};
friend ostream& operator<<(ostream& o, Base& obj)
{
return obj.fun(o,obj.var);
}
};
ostream& odisp(ostream& o, int i);
{
o<<”i=”<<i<<endl;
return o;
}
Base disp(int i)
{
return base(odisp, i)
};
I am totally stuck since the first line since i cant figure out how this typedef works.. it looks like a pointer to function syntax but again ostream has me puzzled..?? pls do explain how this whole code works..??
#include <iostream.h>
#include <conio.h>
As it has been pointed out, iostream.h and conio.h are not standard headers for C++ programs. The correct header include statement for the IO streams library is #include <iostream>, without the extension.
typedef ostream& (*T)(ostream& , int);
This creates a typedef named T which is a pointer to a function with these properties:
returns a reference to ostream
accepts two parameters, in this order:
a reference to an ostream
int value
ostream, assuming it's referring to std::ostream, is itself a typedef of std::basic_ostream, which is found in the C++ standard library. It is defined as:
namespace std {
typedef basic_ostream<char> ostream;
}
Objects std::cout are instances of std::ostream.
class Base
{
T fun; // (1)
int var; // (2)
public:
Base(T func, int arg): fun(func) , var(arg) {}; // (3)
friend ostream& operator<<(ostream& o, Base& obj) // (4)
{
return obj.fun(o, obj.var);
}
};
This is a class that holds two things: (1) a pointer to a function as described above and (2) an integer. The constructor (3) allows users of the class to instantiate it with a function pointer and an integer.
The friend function declaration (4) overloads the left bitshift operator <<. This sort of overloading is called operator overloading. By convention, The operator << is also called the stream insertion operator in the context of IO streams.
Note that friend functions defined this way are actually not members of Base, and thus do not receive a this pointer (hence, the need for a separate Base& parameter).
ostream& odisp(ostream& o, int i);
{
o << "i=" << i << endl;
return o;
}
This is a function called odisp. It takes in a reference to an ostream and an integer. If you pass in the integer 42, it prints out the passed-in integer in this form:
i=42
Base disp(int i)
{
return base(odisp, i)
};
This function has multiple syntax errors and will not run as-is:
base is probably meant to be Base. In this case it would construct a Base temporary and returns it.
Missing a semicolon.
These issues are somewhat fundamental to the language. You may want to pick up a good introductory C++ book which will cover these issues.

Overloading operator ++

Class declaration:
class unaryOperators
{
public:
int i;
unaryOperators (int tempI = 0)
{
i = tempI;
}
unaryOperators operator++ (int);
unaryOperators operator++ ();
};
Does this global definition correspond to postfix or prefix version of the overloaded operator++? Why?
unaryOperators operator++ (unaryOperators &one)
{
return one;
}
unaryOperators& operator++ (unaryOperators &one)
^^
is the non-member prefix unary increment operator.
The non-member postfix unary increment operator takes an additional int as an policy enforcing parameter.
unaryOperators operator++ (unaryOperators &one, int)
Reference:
C++03 Standard 13.5.7 Increment and decrement [over.inc]
The user-defined function called operator++ implements the prefix and postfix ++ operator. If this function is a member function with no parameters, or a non-member function with one parameter of class or enumeration type, it defines the prefix increment operator ++ for objects of that type. If the function is a member function with one parameter (which shall be of type int) or a non-member function with two parameters (the second of which shall be of type int), it defines the postfix increment operator ++ for objects of that type. When the postfix increment is called as a result of using the ++ operator, the int argument will have value zero.125)
[Example:
class X {
public:
X& operator++(); // prefix ++a
X operator++(int); // postfix a++
};
class Y { };
Y& operator++(Y&); // prefix ++b
Y operator++(Y&, int); // postfix b++
void f(X a, Y b) {
++a; // a.operator++();
a++; // a.operator++(0);
++b; // operator++(b);
b++; // operator++(b, 0);
a.operator++(); // explicit call: like ++a;
a.operator++(0); // explicit call: like a++;
operator++(b); //explicit call: like ++b;
operator++(b, 0); // explicit call: like b++;
}
—end example]
I think this will help you.
Every operator (that can be overloaded as a free function) takes one more argument when overloaded as a free function. The first argument corresponds to *this when overloaded as a member function.
bool AsMember::operator!() const;
bool operator!(const AsFreeFunction&);
bool AsMember::operator==(const AsMember& rhv) const;
bool operator==(const AsFreeFunction& lhv, const AsFreeFunction& rhv);
etc.
Increment operator is no exception to this.
Global overloaded operator++ functions expect the explicit specification of all the arguments, so if the overloaded operator ++ is postfix, we are supposed to add one default int argument (to distinguish postfix version from prefix) in addition to the prerequisite one (which determines the type on which the function needs to be applied).
unaryOperators operator++ (unaryOperators &one, int dummy)
{
return one;
}
In the case of prefix global overloaded operator++ functions, the only argument we need to specify is the prerequisite one (which determines the type on which the function needs to be applied).
unaryOperators operator++ (unaryOperators &one)
{
return one;
}
The free function is prefix as it lacks an int parameter.
Helpful guide for operator signatures.
The canonical version of preincrement is:
T &operator++(T &)
That is, return the operand by reference. Postincrement takes an unused int, so the global operator++ you defined is the preincrement operator.

How do I create a class that can initialize C++ data types?

The title basically says it all. I mainly want to do this so that I can create an object (say, a custom string object) that can initialize the parameters of other functions in other APIs. Here's an example of me trying to get a custom integer class to work:
#include <iostream>
using namespace std;
class test
{
public:
int member;
test(int i) : member(i) {}
friend int &operator=(int &i, test t);
};
int &operator=(int &i, test t)
{
return (i = t.member);
}
int main()
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
Unfortunately I receive an error saying that operator= needs to be a member function. I understand the C++ standard's goal in preventing static and non-member overloads for the assignment operator from being implemented, but is there any other way to do this? Thanks for any help/suggestions!
This is not done with an assignment operator but with an overloaded typecast. This would make your main function work like expected:
#include <iostream>
using namespace std;
class test
{
public:
int member;
test(int i) : member(i) {}
operator int() const {return member;}
};
int main()
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
What you are trying to do needs an conversion operator
operator int()
{
return this->member;
}
For the class you are trying to write(containing only integer members), You do not need to overload the = operator.
= operator is one of the member functions that is generated by the compiler by default for every class. Caveat is, it does a simple bit by bit copy(shallow copy) of class members, since you have only integers it should be good enough for you.
You would need to overload the = operator if you had dynamically allocated pointers as member functions, because in that case a shallow copy of those pointers would result in all the objects containing a member pointer pointing to the same dynamic memory location & if one of the object finishes it lifetime, other objects are left with a dangling pointer.
As #Tony, aptly points in out comments Shallow copy is usually bad but not always. See his comments for a scenario.
If at all you want to overload the assignment operator check out the Copy and Swap Idiom to do it right way.
You should also check out the Rule of Three.
Try this:
class test
{
public:
int member;
test(int i) : member(i) {}
operator int() {return this->member;}
};
int main(void)
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
The assignment operator cannot be a friend function. The assignment operator can only be declared as a non-static member function. This is to ensure that it receives the L-value as its first operand. The same is true for the [], (), and -> operators. In your case, since int is an build-in type, you cannot use member function. You can implement operator int() to cast your user-defined type to int.