What is it? It is the coder’s ability to add additional abilities to operators such as +, - *, %, etc… Here is a complete list of operators that can be overloaded in C++:
CODE
* / + - % ^ & | ! , = < > <= >= ++ -- << >> == != && || *= /= %= ^= &= |= += -= <<= >>= -> ->* [] () new delete
These operators cannot be overloaded:
CODE
., .*, ::, ?:, and sizeof
Below is an example of using an increment operator without overloading it
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
return 0;
}
}
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
return 0;
}
}
Output: The value of i is 0
The value of 1 is 1
Now this works; it allows the class to be incremented but it does not truly overload the ++ operator yet. Plus this method can eventually get too cumbersome to use. So how does one overload the prefix increment operator?
Default syntax for overloading an operator:
CODE
returnType operator op()
example:
CODE
void operator++()
This sample code shows how to overload the ++ operator:
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
void operator++() {++itsVal;}
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
return 0;
}
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
void operator++() {++itsVal;}
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
return 0;
}
Output: The value of i is 0
The value of i is 1
The value of i is 2
In the code, the operator ++ is overloaded. Albeit simple, it simply increments the Counter object's private variable itsVal. The use of this operator being overloaded brings it closer to the use of increment operators when used on an integer, etc...
Now say for example, if you wanted to assign a new Counter object 'a' to the value that 'i' currently has like this:
CODE
Counter a = ++i;
This will fail. The code intends to assign the value of 'i' to a new Counter object 'a'. The program's built in copy constructor can handle the assignment, but the current overloaded operator function is void, it is not set to return anything, much less a Counter object. One possible solution is to create a temporary object and return that:
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
Counter operator++();
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
Counter Counter::operator ++()
{
++itsVal;
Counter temp; //temp counter object created here
temp.SetItsVal(itsVal);
return temp;
}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
Counter a = ++i;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
Counter operator++();
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
Counter Counter::operator ++()
{
++itsVal;
Counter temp; //temp counter object created here
temp.SetItsVal(itsVal);
return temp;
}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
Counter a = ++i;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}
Output: The value of i is 0
The value of i is 1
The value of i is 2
The value of a: 3 and i: 3
The operator++ function now creates a temp object and can be used when transferring data from one class object to another. The temp value that is returned is immediately assigned to a. Since a temp object must be created and later destroyed, this way of accomplishing the problem will eventually cause problems as well, way too much overhead and potentially a very expensive operation.
To make this use less memory, we will use the ‘this’ pointer:
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
const Counter& operator++();
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
const Counter& Counter::operator ++()
{
++itsVal;
return *this;
}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
Counter a = ++i;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
const Counter& operator++();
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
const Counter& Counter::operator ++()
{
++itsVal;
return *this;
}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
Counter a = ++i;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}
Output: The value of i is 0
The value of i is 1
The value of i is 2
The value of a: 3 and i: 3
Using ‘this’ has made the code cleaner and more efficient.
Now, we have gone over overloading the prefix operator, but what about the postfix one? Instead of incrementing and then fetching, we must now fetch and then increment. For the initial code for this we will be creating a temporary object again, why? Consider this following segment:
CODE
a = x++;
If x has a value of 6, 'a' is assigned that value and x then becomes 7. If x is an object in this instance, the postfix increment operator needs to stash x's original value away, increment, then assign the new value to a. However this cannot be passed by reference, because immediately after it's done the temp object will go out of scope:
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
const Counter& operator++(); //prefix
const Counter operator++(int); //postfix
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
const Counter& Counter::operator ++()
{
++itsVal;
return *this;
}
const Counter Counter::operator ++(int theFlag)
{
Counter temp(*this);
++itsVal;
return temp;
}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
Counter a = ++i;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
a = i++;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}
using namespace std;
class Counter
{
public:
Counter();
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
const Counter& operator++(); //prefix
const Counter operator++(int); //postfix
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::~Counter()
{}
const Counter& Counter::operator ++()
{
++itsVal;
return *this;
}
const Counter Counter::operator ++(int theFlag)
{
Counter temp(*this);
++itsVal;
return temp;
}
int main()
{
Counter i; //declares a counter object'i'
cout << "The value of i is " << i.GetItsVal() << endl;
i.Increment();
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
Counter a = ++i;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
a = i++;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}
Output: The value of i is 0
The value of i is 1
The value of i is 2
The value of a: 3 and i: 3
The value of a: 3 and i: 4
The parameter passed into the postfix operator is used simply to differentiate and that the compiler knows which one to use, the actual value of 'theFlag' is never used.
Now to overloading binary operators:
Binary Operators
Unlike increments/decrements, operators such as addition (+), multiplication (*), division (/), and subtraction (-) will have to deal with two numbers, two objects, two of anything etc... to perform their function. Having this in mind, overloading their function will be different then the examples above:
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
Counter(int initialValue);
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
Counter Add(const Counter &);
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::Counter(int initialValue):
itsVal(initialValue)
{}
Counter::~Counter()
{}
Counter Counter::Add(const Counter &rhs)
{
return Counter(itsVal + rhs.GetItsVal());
}
int main()
{
Counter varOne(2), varTwo(4), varThree;
varThree = varOne.Add(varTwo);
cout << "varOne: " << varOne.GetItsVal() << endl;
cout << "varTwo: " << varTwo.GetItsVal() << endl;
cout << "varThree: " << varThree.GetItsVal() << endl;
return 0;
}
using namespace std;
class Counter
{
public:
Counter();
Counter(int initialValue);
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
Counter Add(const Counter &);
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::Counter(int initialValue):
itsVal(initialValue)
{}
Counter::~Counter()
{}
Counter Counter::Add(const Counter &rhs)
{
return Counter(itsVal + rhs.GetItsVal());
}
int main()
{
Counter varOne(2), varTwo(4), varThree;
varThree = varOne.Add(varTwo);
cout << "varOne: " << varOne.GetItsVal() << endl;
cout << "varTwo: " << varTwo.GetItsVal() << endl;
cout << "varThree: " << varThree.GetItsVal() << endl;
return 0;
}
Output: varOne: 2
varTwo: 4
varThree: 6
The Add() function is new in this listing and takes a const reference to a Counter object; it returns a Counter object. An additional constructor is created because varOne and varTwo need to be initialized to a nonzero value anmd the default one would not suffice.
Although we have defined a new function Add(), it does not overload the operator+, here is it overloaded:
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
Counter(int initialValue);
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
Counter operator+ (const Counter &);
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::Counter(int initialValue):
itsVal(initialValue)
{}
Counter::~Counter()
{}
Counter Counter::operator+(const Counter &rhs)
{
return Counter(itsVal + rhs.GetItsVal());
}
int main()
{
Counter varOne(2), varTwo(4), varThree;
varThree = varOne + varTwo;
cout << "varOne: " << varOne.GetItsVal() << endl;
cout << "varTwo: " << varTwo.GetItsVal() << endl;
cout << "varThree: " << varThree.GetItsVal() << endl;
return 0;
}
using namespace std;
class Counter
{
public:
Counter();
Counter(int initialValue);
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
void Increment() {++itsVal;}
Counter operator+ (const Counter &);
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::Counter(int initialValue):
itsVal(initialValue)
{}
Counter::~Counter()
{}
Counter Counter::operator+(const Counter &rhs)
{
return Counter(itsVal + rhs.GetItsVal());
}
int main()
{
Counter varOne(2), varTwo(4), varThree;
varThree = varOne + varTwo;
cout << "varOne: " << varOne.GetItsVal() << endl;
cout << "varTwo: " << varTwo.GetItsVal() << endl;
cout << "varThree: " << varThree.GetItsVal() << endl;
return 0;
}
Output: varOne: 2
varTwo: 4
varThree: 6
Note that the output is exaclty the same, excpet we have just overloaded the operator+. You can use this method to overload any arithmetic type, add, subtract, etc...
Overloading operators << and []
This next portion assumes you understand how ‘friend’ functions work. The syntax for these operators is essentially the same as above, but requires modification in regards to what classes/objects they are being placed into:
CODE
type operator[](parameter list)
type operator<<(parameter list)
type operator<<(parameter list)
This code is a good example of how both of these are used in regards to strings. When you have printed a string in the past it was:
CODE
cout << theString.GetString();
What we “want” to do is this:
CODE
cout << theString;
See here:
CODE
#include <iostream>
#include <string.h>
using namespace std;
class String
{
public:
String();
String(const char *const);
String(const String &);
~String();
//overloaded operators
char & operator[](int offset);
char operator[](int offset) const;
String operator+(const String&);
void operator+=(const String&);
String & operator= (const String&);
friend ostream& operator<<
(ostream& theStream, String& theString);
int GetLen()const {return itsLen;}
const char * GetString() const {return itsString;}
private:
String (int);
char * itsString;
unsigned short itsLen;
};//end String class
String::String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLen = 0;
}
String::String(int len)
{
itsString = new char [len+1];
for(int i = 0; i <= len; i++)
itsString[i] = '\0';
itsLen = len;
}
String::String(const char * const cString)
{
itsLen = strlen(cString);
itsString = new char[itsLen+1];
for (int i = 0; i <itsLen; i++)
itsString[i] = cString[i];
itsString[itsLen] = '\0';
}
String::String(const String & rhs)
{
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i =0; i< itsLen; i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
}
String::~String()
{
delete [] itsString;
itsLen = 0;
}
String& String::operator=(const String & rhs)
{
if (this == &rhs)
return *this;
delete [] itsString;
itsLen = rhs.GetLen();
itsString = new char [itsLen +1];
for (int i = 0; i <itsLen; i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
return *this;
}
char & String::operator [](int offset)
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
char String::operator [](int offset) const
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
String String::operator +(const String & rhs)
{
int totalLen = itsLen + rhs.GetLen();
String temp(totalLen);
int i, j;
for (i = 0; i < itsLen; i++)
temp[i] = itsString[i];
for(j = 0; j < rhs.GetLen(); j ++)
temp[i] = rhs[j];
temp[totalLen]='\0';
return temp;
}
void String::operator +=(const String &rhs)
{
unsigned short rhsLen = rhs.GetLen();
unsigned short totalLen = itsLen + rhsLen;
String temp(totalLen);
int i, j;
for (i=0; i<itsLen; i++)
temp[i] = itsString[i];
for(j=0, i=0; j<rhs.GetLen(); j++, i++)
temp[i] = rhs[i-itsLen];
temp[totalLen] = '\0';
*this = temp;
}
ostream& operator<< (ostream& theStream, String& theString)
{
theStream << theString.itsString;
return theStream;
}
int main()
{
String theString("Example of Overloading Operators\n");
cout << theString;
return 0;
}
#include <string.h>
using namespace std;
class String
{
public:
String();
String(const char *const);
String(const String &);
~String();
//overloaded operators
char & operator[](int offset);
char operator[](int offset) const;
String operator+(const String&);
void operator+=(const String&);
String & operator= (const String&);
friend ostream& operator<<
(ostream& theStream, String& theString);
int GetLen()const {return itsLen;}
const char * GetString() const {return itsString;}
private:
String (int);
char * itsString;
unsigned short itsLen;
};//end String class
String::String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLen = 0;
}
String::String(int len)
{
itsString = new char [len+1];
for(int i = 0; i <= len; i++)
itsString[i] = '\0';
itsLen = len;
}
String::String(const char * const cString)
{
itsLen = strlen(cString);
itsString = new char[itsLen+1];
for (int i = 0; i <itsLen; i++)
itsString[i] = cString[i];
itsString[itsLen] = '\0';
}
String::String(const String & rhs)
{
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (int i =0; i< itsLen; i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
}
String::~String()
{
delete [] itsString;
itsLen = 0;
}
String& String::operator=(const String & rhs)
{
if (this == &rhs)
return *this;
delete [] itsString;
itsLen = rhs.GetLen();
itsString = new char [itsLen +1];
for (int i = 0; i <itsLen; i++)
itsString[i] = rhs[i];
itsString[itsLen] = '\0';
return *this;
}
char & String::operator [](int offset)
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
char String::operator [](int offset) const
{
if (offset > itsLen)
return itsString[itsLen-1];
else
return itsString[offset];
}
String String::operator +(const String & rhs)
{
int totalLen = itsLen + rhs.GetLen();
String temp(totalLen);
int i, j;
for (i = 0; i < itsLen; i++)
temp[i] = itsString[i];
for(j = 0; j < rhs.GetLen(); j ++)
temp[i] = rhs[j];
temp[totalLen]='\0';
return temp;
}
void String::operator +=(const String &rhs)
{
unsigned short rhsLen = rhs.GetLen();
unsigned short totalLen = itsLen + rhsLen;
String temp(totalLen);
int i, j;
for (i=0; i<itsLen; i++)
temp[i] = itsString[i];
for(j=0, i=0; j<rhs.GetLen(); j++, i++)
temp[i] = rhs[i-itsLen];
temp[totalLen] = '\0';
*this = temp;
}
ostream& operator<< (ostream& theStream, String& theString)
{
theStream << theString.itsString;
return theStream;
}
int main()
{
String theString("Example of Overloading Operators\n");
cout << theString;
return 0;
}
By overloading the [] and << operators, we were able to display a string without an extra function call.
The Assignment Operator= ()
This operator comes in handy when you want to assign the value of one object to another. This can create confusion as there are shallow copies (just the members) and a deep copy (which allocates the necessary memory for that object). Example:
CODE
Cat catOne(5,7);
Cat catTwo(3,4);
// some other code....
catTwo = catOne;
Cat catTwo(3,4);
// some other code....
catTwo = catOne;
This snippet has each object with a few of its assigned member values. What if you wanted to assign them to something else?
CODE
catTwo = catTwo;
I doubt anyone would do this on purpose, but it is possible for it happen by accident when references and dereferenced pointers hide the fact that this assignment is to itself. If this was not handled catTwo would delete its own memory allocation and then when it was ready to copy from the right side, there would be nothing there... For protection against this any assignment operator you create must check for itself using the 'this' pointer discussed earlier:
CODE
# include <iostream>
using namespace std;
class Cat
{
public:
Cat();
//copy constructor and destructor omitted
int GetAge()const {return *itsAge;}
int GetWeight()const {return *itsWeight;}
void SetAge(int age){*itsAge = age;}
Cat & operator=(const Cat&);
private:
int *itsAge;
int *itsWeight;
};
Cat::Cat()
{
itsAge = new int;
itsWeight = new int;
*itsAge = 5;
*itsWeight = 9;
}
Cat & Cat::operator=(const Cat & rhs)
{
if (this == &rhs)
return *this;
*itsAge = rhs.GetAge();
*itsWeight = rhs.GetWeight();
return *this;
}
int main()
{
Cat Frisky;
cout << "Frisky's age: " << Frisky.GetAge() << endl;
cout << "Setting Frisky's age to 6...\n";
Frisky.SetAge(6);
Cat Whiskers;
cout << "Whisker's age: " << Whiskers.GetAge() << endl;
cout << "copying Frisky to Whiskers....\n";
Whiskers = Frisky;
cout << "Whiskers's age: " << Whiskers.GetAge() << endl;
return 0;
}
using namespace std;
class Cat
{
public:
Cat();
//copy constructor and destructor omitted
int GetAge()const {return *itsAge;}
int GetWeight()const {return *itsWeight;}
void SetAge(int age){*itsAge = age;}
Cat & operator=(const Cat&);
private:
int *itsAge;
int *itsWeight;
};
Cat::Cat()
{
itsAge = new int;
itsWeight = new int;
*itsAge = 5;
*itsWeight = 9;
}
Cat & Cat::operator=(const Cat & rhs)
{
if (this == &rhs)
return *this;
*itsAge = rhs.GetAge();
*itsWeight = rhs.GetWeight();
return *this;
}
int main()
{
Cat Frisky;
cout << "Frisky's age: " << Frisky.GetAge() << endl;
cout << "Setting Frisky's age to 6...\n";
Frisky.SetAge(6);
Cat Whiskers;
cout << "Whisker's age: " << Whiskers.GetAge() << endl;
cout << "copying Frisky to Whiskers....\n";
Whiskers = Frisky;
cout << "Whiskers's age: " << Whiskers.GetAge() << endl;
return 0;
}
Output: Frisky's age: 5
Setting Frisky's age to 6...
Whisker's age: 5
copying Frisky to Whiskers
Whisker's age: 6
Data conversion was handled and would not cause an error is an object is assigned to itself. Going back to the Counter example, what happens if you wished to assign an integer value to a Counter object? There would be an error. This is how to handle such problems:
CODE
#include <iostream>
using namespace std;
class Counter
{
public:
Counter();
Counter(int val);
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
operator unsigned int();
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::Counter(int val):
itsVal(val)
{}
Counter::~Counter()
{}
Counter::operator unsigned int()
{
return (int (itsVal));
}
int main()
{
Counter ctr(5);
int someInt = ctr;
cout << "someInt: " << someInt << endl;
return 0;
}
using namespace std;
class Counter
{
public:
Counter();
Counter(int val);
~Counter();
int GetItsVal()const {return itsVal;}
void SetItsVal(int x) {itsVal = x;}
operator unsigned int();
private:
int itsVal;
};
Counter::Counter():
itsVal(0)
{}
Counter::Counter(int val):
itsVal(val)
{}
Counter::~Counter()
{}
Counter::operator unsigned int()
{
return (int (itsVal));
}
int main()
{
Counter ctr(5);
int someInt = ctr;
cout << "someInt: " << someInt << endl;
return 0;
}
By creating a conversion operator, the program now can switch between ints and Counter objects, vice versa, you can even add other data types, etc...
Limitations on Operaton Overloading
Operators for built in types (such as int, double) cannot be overloaded. Also the precedence order cannot be changed, nor the arity of the operator, i.e. unary or binary. As fun as it sounds, you can't create your own "new" operators like '**' being a power operator.
You could also make the operator+ subtract and the operator * divide, which shows the powerful abilities this has, but also shows impracticality. Code that is easier to read, smooth, concise, and practical is better then confusing pointless code.
Hope this helped you in regards to overloading operators in C++. Any extra input/criticism would be greatly appreciated.
