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.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.

This entry was posted in C++ Tutorials. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. Tweet This! Tweet This! or use to share this post with others.

There are currently 24 responses to “C++ Unary and binary operator overloading and static members”

Why not let us know what you think by adding your own comment!

  1. sabera on November 6th, 2009:

    itz very useful to me and its helped me to update my knowledge

  2. abhishek on December 5th, 2009:

    its amazing..
    its very easy understandable…
    thank..

  3. Hala Khanji on May 1st, 2010:

    Thaaaaaaaaaaaaaaaaaaaaaaank you very much! You really helped me out :). You see my doctors suck at teaching!

  4. Tim on June 22nd, 2010:

    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

  5. admin on June 22nd, 2010:

    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!

  6. Tim on June 23rd, 2010:

    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.

  7. admin on June 24th, 2010:

    @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.

  8. Ravindra on October 10th, 2010:

    This is good example of binary over overloading. This will help in my exam.

  9. prince on December 2nd, 2010:

    hi i want to overload <> operators

  10. admin on December 5th, 2010:

    @prince : we’ve added a small tutorial on overloading of > and < binary operators

    We hope it helps!

  11. Aishwarya on January 9th, 2011:

    Hmm….. Very simple program that every one can understand….!!! Thank uuuuuuu…….!!!!!!

  12. as on January 17th, 2011:

    thanks…its very useful to me to understand this part

  13. $$$ on February 26th, 2011:

    #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();
    }

  14. neetu mishra on December 11th, 2011:

    thanks a lot for this easily understandable view—————

  15. Manish Sohodebd on December 12th, 2011:

    Overload operator + and – for fraction using friend and then compute 2/3+1/2 in the main function.How can i do it??

  16. sasi on March 15th, 2012:

    thanks a lot for easy understand

  17. Hassan on March 21st, 2012:

    this is very helpful….

  18. Ghani Ur Rehman on May 3rd, 2012:

    This website is very much helpful for students in all the world

  19. Sooraj P George on December 17th, 2012:

    Thanks a lot.
    Keep it up.

  20. Priya on January 5th, 2013:

    It is useful for me

  21. Sanjeev on February 13th, 2013:

    Thanks for the simple & very useful programs. It will really help me in my profession.

  22. manoj on March 21st, 2013:

    unary and binary overload ka pro. c++ me kise hoga

  23. hari on April 9th, 2013:

    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???

  24. mahwish on June 28th, 2013:

    hw can v overload unary as well as binary operator using friend function in jus one progrm…….

Leave a Reply: