C++ Unary and binary operator overloading and static members
We hope that you enjoyed our previous tutorial on C++ overloading. Today we take another look at operator overloading in the C++ programming language.
Unary and binary operator overloading
There are two types of operator overloading:
- Unary operator overloading
- Binary operator overloading
(You can find the complete unary and binary operator table here.)
Whenever an unary operator is used, it works with one operand, therefore with the user defined data types, the operand becomes the caller and hence no arguments are required.
Take a look at the following unary operator overloading example, in this case the unary operators increment (++) and decrement (–):
#include<iostream>
using namespace std;
//Increment and decrement overloading
class Inc {
private:
int count ;
public:
Inc() {
//Default constructor
count = 0 ;
}
Inc(int C) {
// Constructor with Argument
count = C ;
}
Inc operator ++ () {
// Operator Function Definition
return Inc(++count);
}
Inc operator -- () {
// Operator Function Definition
return Inc(--count);
}
void display(void) {
cout << count << endl ;
}
};
void main(void) {
Inc a, b(4), c, d, e(1), f(4);
cout << "Before using the operator ++()\n";
cout << "a = ";
a.display();
cout << "b = ";
b.display();
++a;
b++;
cout << "After using the operator ++()\n";
cout << "a = ";
a.display();
cout << "b = ";
b.display();
c = ++a;
d = b++;
cout << "Result prefix (on a) and postfix (on b)\n";
cout << "c = ";
c.display();
cout << "d = ";
d.display();
cout << "Before using the operator --()\n";
cout << "e = ";
e.display();
cout << "f = ";
f.display();
--e;
f--;
cout << "After using the operator --()\n";
cout << "e = ";
e.display();
cout << "f = ";
f.display();
}
As mention before the overloaded operator function above is an example of unary operator overloading. But you may have notice that when compiling the compiler will give some warnings. For example in Visual C++ the warnings will look something like this:
warning C4620: no postfix form of 'operator ++' found for type 'Inc', using prefix form
As you can see the postfix (b++) overloaded function can not be found so the prefix (++a) is used by the compiler. What we need are two operator overloaded functions of the exact same signature. Bjarne Stroustrup has provided the solution by introducing the concept of dummy argument, so that it becomes function overloading for the operator overloaded functions. Take a look at the example:
#include<iostream>
using namespace std;
//Increment and decrement overloading
class Inc {
private:
int count ;
public:
Inc() {
//Default constructor
count = 0 ;
}
Inc(int C) {
// Constructor with Argument
count = C ;
}
Inc operator ++ () {
// Operator Function Definition
// for prefix
return Inc(++count);
}
Inc operator ++ (int) {
// Operator Function Definition
// with dummy argument for postfix
return Inc(count++);
}
Inc operator -- () {
// Operator Function Definition
// for prefix
return Inc(--count);
}
Inc operator -- (int) {
// Operator Function Definition
// with dummy argument for postfix
return Inc(count--);
}
void display(void) {
cout << count << endl ;
}
};
int main() {
Inc a, b(4), c, d, e(1), f(4);
cout << "Before using the operator ++()\n";
cout << "a = ";
a.display();
cout << "b = ";
b.display();
++a;
b++;
cout << "After using the operator ++()\n";
cout << "a = ";
a generic lipitor.display();
cout << "b = ";
b.display();
c = ++a;
d = b++;
cout << "Result prefix (on a) and postfix (on b)\n";
cout << "c = ";
c.display();
cout << "d = ";
d.display();
cout << "Before using the operator --()\n";
cout << "e = ";
e.display();
cout << "f = ";
f.display();
--e;
f--;
cout << "After using the operator --()\n";
cout << "e = ";
e.display();
cout << "f = ";
f.display();
return 0;
}
As you can see in this case we use int as a dummy argument for post-fix, when we redefine the functions for the unary increment (++) and decrement (–) overloaded operators. You must remember that int isn’t an integer, but just a dummy argument. You can see it as a signal to the compiler to create the post-fix notation of the operator.
Whenever a binary operator is used – it works with two operands, therefore with the user defined data types – the first operand becomes the operator overloaded function caller and the second is passed as an argument. This results in compulsion of receiving one argument in overloading of the binary operators. Let’s look at an example of binary operator overloading:
#include<iostream>
using namespace std;
class Rational
{
private:
int num; // numerator
int den; // denominator
public:
void show();
Rational(int=1,int=1);
void setnumden(int,int);
Rational add(Rational object);
Rational operator+(Rational object);
bool operator==(Rational object);
bool operator!=(Rational object);
};
void Rational::show() {
cout << num << "/" << den << "\n";
}
Rational::Rational(int a,int b) {
setnumden(a,b);
}
void Rational::setnumden(int x,int y) {
int temp,a,b;
a = x;
b = y;
if(b > a) {
temp = b;
b = a;
a = temp;
}
while(a != 0 && b != 0) {
if(a % b == 0)
break;
temp = a % b;
a = b;
b = temp;
}
num = x / b;
den = y / b;
}
Rational Rational::add(Rational object) {
int new_num = num * object.den + den * object.num;
int new_den = den * object.den;
return Rational(new_num, new_den);
}
Rational Rational::operator+(Rational object) {
int new_num = num * object.den + den * object.num;
int new_den = den * object.den;
return Rational(new_num, new_den);
}
bool Rational::operator==(Rational object) {
return (num == object.num && den == object.den);
}
bool Rational::operator!=(Rational object) {
return (num != object.num || den != object.den);
}
int main() {
Rational obj1(1,4), obj2(210,840), result1;
result1 = obj1.add(obj2);
result1.show();
Rational obj3(1,3), obj4(33,99), result2;
result2 = obj3 + obj4;
result2.show();
Rational obj5(10,14), obj6(25,35), obj7(2,3), obj8(1,2);
if(obj5 == obj6) {
cout << "The two fractions are equal." << endl;
}
if(obj7 != obj8) {
cout << "The two fractions are not equal." << endl;
}
return 0;
}
As you can see we used the binary operator plus (+), equal (==) and not-equal (!=) and all function work with two operands. The first (Rational) is the operator overloaded function caller and the second (object) is the passed argument.
You can find the source code of unary and binary operator overloading here.
Static Members
Static means something maintaining state either forever or up to some point. In C++, static members get their life active as soon as the execution of the program starts, no matter, whether they are created in local,
global or class scope.
Following points are to be noted regarding the static members:
- They are allocated as soon as the execution of program starts, regardless of their scope.
- They are de-allocated at the end of the program execution.
- Since they have lifetime, during the whole of the program execution, they retain the values in them.
- They are usable in their scope only though their life is for the whole of the program execution.
- On creation, they are initialized with ZERO.(other locally created variables shall get some undefined (garbage) value in them).
#include<iostream>
using namespace std;
class Test {
public:
static int objCounter;
Test()
{
Test::objCounter++;
}
~Test()
{
Test::objCounter--;
}
};
int Test::objCounter;
int main(int argc, char * argv[]) {
Test obj1, *ptr, obj2;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 2
ptr= new Test;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 3
delete ptr;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 2
return 0;
}
The program above discusses the use of static for maintaining the statistics of the objects created for the Test class.
Following are the important points specific to CPP:
- Static members of the class must be re-declared outside the class (globally).
- Static data member can be used directly in static member functions only, otherwise they are used using Scope Resolution Operator.
- Static members are created only once as soon as the execution of the program starts and the same is shared among all the objects (obj1, obj2, *ptr) of the class.
- Static members are constrained by the access modifiers (public, private, protected).
- Static functions can only use static data members or local variables, it can not use non static data members of the class.
#include<iostream>
using namespace std;
class Test1
{
static int testvar;
int testvar1; //non static member
public:
static void testfunc()
{
cout << endl << "Value of static variable : " << testvar;
//Non static members can not be used in static functions.
//cout << endl << "Value of nonstatic variable : " << testvar1;
}
};
int Test1::testvar;
int main(int argc, char *argv[]) {
Test1::testfunc();
return 0;
}
Note: Remove the // for the second cout. You should get a compile error, something like:
error C2597: illegal reference to non-static member ‘Test1::testvar1’
That is all for this tutorial.
Also take a look at the overloading tutorial of > and < binary operators for a further example of operator overloading.
itz very useful to me and its helped me to update my knowledge
its amazing..
its very easy understandable…
thank..
Thaaaaaaaaaaaaaaaaaaaaaaank you very much! You really helped me out :). You see my doctors suck at teaching!
EDIT: see comment of the admin below! The code in mentioned in this comment is not used in the re-written C++ tutorial.
Original comment:
In this tutorial, pre- and post-increment are implemented identical. This is not correct. They are not the same thing. The difference is that post-increment will return the OLD value. They should be more like this:
Rational& operator++()
{
num += den;
return *this;
}
Rational operator++(int)
{
Rational old_value(*this);
++(*this); // Or you could just write: num += den;
return old_value;
}
kthxbye
Tim, you are right! So we have re-written the tutorial.
The new tutorial (see above) should be much easier to understand than the old one.
It also has more (larger and complete) examples and we’ve added a download link to the source.
Also added a link to an unary and binary operator table .
So we hope you and the other visitors will like it!
Well, I must say, while I can see you improved the tutorial, my point is still not addressed. Try using normal ints instead of Inc instances, you’ll see what I mean:
int a = 0;
int b = a++;
cout << a << endl; // This prints 1, ok.
cout << b << endl; // This prints 0, not 1!
This tutorial program prints this:
Result prefix (on a) and postfix (on b)
c = 2
d = 6
While it should really print this:
Result prefix (on a) and postfix (on b)
c = 2
d = 5
This is because Inc operator++(int) is not implemented correctly.
@Tim
Yes, I see what you mean now. (I always did a postfix instead of a prefix and postfix). I’ve corrected the example and also changed the other examples to things you send by email.
Thank you for helping to improve this tutorial.
This is good example of binary over overloading. This will help in my exam.
hi i want to overload <> operators
@prince : we’ve added a small tutorial on overloading of > and < binary operators
We hope it helps!
Hmm….. Very simple program that every one can understand….!!! Thank uuuuuuu…….!!!!!!
thanks…its very useful to me to understand this part
#include
using namespace std;
class complex
float x,y;
public:
complex()
{
}
complex(float real,float img)
{
x=real;
y=img;
}
complex operator +(complex);
void display(void);
};
complex complex:operator +(complex c)
{
complex temp;
temp.x=x+c.x;
temp.y=y+c.y;
return(temp);
}
void complex::display(void);
{
cout<<x<<"+j"<<y;
}
main()
{
complex c1,c2,c3;
c1=complex(2,3)
ccomplex(1,2);
c3=c1+c2;
cout<<c1;
c1.display();
cout<<c2;
c2.display();
cout<<c3;
c3.display();
}
thanks a lot for this easily understandable view—————
Overload operator + and – for fraction using friend and then compute 2/3+1/2 in the main function.How can i do it??
thanks a lot for easy understand
this is very helpful….
This website is very much helpful for students in all the world
Thanks a lot.
Keep it up.
It is useful for me
Thanks for the simple & very useful programs. It will really help me in my profession.
unary and binary overload ka pro. c++ me kise hoga
In a simple unary plus operator overloading program, should the input always be given in minus ( ie. like -2,-4..) if we give input in minus then what is the output???
Example-
class d
{
int x,y;
public:
void getdata()
{
x=-3; y=4
}
void display()
{
cout<<x<<y;
}
void operator+()
{
x=+x;
y=+y;
}
};
int main()
{
d s;
s.getdata();
s.display();
+s;
s.display();
return 0;
}
output???
hw can v overload unary as well as binary operator using friend function in jus one progrm…….