Operator Overloading
Overview:
This chapter discuss about the operator overloading in C++. It is common used component in C++ programming. Personally speaking, the most used operator overloading is the comparison function operator<. However, this time we cover the knowledges more than this. The concept covers basic operator+/*, prefix/postfix increment, array index, input/output stream, and input/output file stream. Talk is cheap, there is the code.
Class declaration:
// console cin, cout
#include<iostream>
// file in, out
#include<fstream>
using namespace std;
class ThreeD{
public:
int ht;
int wid;
int dep;
// default constructor
ThreeD() {
ht = wid = dep = 0;
}
// know knid of constructor
ThreeD(int i, int j, int k): ht(i), wid(j), dep(k) {}
int getVol(){ return ht * wid * dep; }
// overload operator
ThreeD operator+(ThreeD t);
ThreeD operator*(ThreeD t);
ThreeD operator++(); // prefix
ThreeD operator++(int neverUsed); // postfix
int & operator[](int k);
//friend: allow function to access private paramenter
friend ostream& operator<<(ostream& str, const ThreeD t);
friend istream& operator>>(istream& str, ThreeD& t);
};
Implementing operator+:
ThreeD ThreeD::operator+(ThreeD t){
ThreeD temp;
temp.ht = ht;
temp.wid = t.wid;
temp.dep = dep + t.dep;
return temp;
}
Implementing operator*:
ThreeD ThreeD::operator*(ThreeD t){
ThreeD temp;
temp.ht = ht * t.ht;
temp.wid = wid * t.wid;
temp.dep = dep * t.dep;
return temp;
}
Implementing operator+:
ThreeD ThreeD::operator+(ThreeD t){
ThreeD temp;
temp.ht = ht;
temp.wid = t.wid;
temp.dep = dep + t.dep;
return temp;
}
Implementing prefix increment:
// prefix
// complier knows that the operator without argument is prefix
ThreeD ThreeD::operator++(){
++ht;
++wid;
++dep;
// this is a pointer pointing to the current object
return *this;
}
Implementing post increment:
// postfix
// complier knows that the operator with argument is postfix
// store the value first,which will be return at the end
// then, apply the increment.
ThreeD ThreeD::operator++(int neverUsed){
ThreeD tmp = *this;
ht++;
wid++;
dep++;
return tmp;
}
Implementing operator[]:
// if defined in this way, it's read-only
// const int & ThreeD::operator[](int k)
//The origianl object will be returned to the calling function.
//No extra copying effort is needed. It is faster than return by value,
//which requires an extra copy to be created and returned to the calling function.
//Because an object is returned, rather than a value, the function can appear
//on the left side of an statement.
int & ThreeD::operator[](int k){
switch(k){
case 0:
// ht will be directly used in calling function
return ht;
case 1:
return wid;
case 2:
return dep;
}
}
Implementing operator<<:
ostream& operator<<(ostream& str, const ThreeD t) {
str << "[" << t.ht << ", " << t.wid << ", " << t.dep << "]";
return str;
}
Implementing operator>>:
istream& operator>>(istream& str, ThreeD& t) {
str >> t.ht >> t.wid >> t.dep;
return str;
}
Implementing operator>>:
istream& operator>>(istream& str, ThreeD& t) {
str >> t.ht >> t.wid >> t.dep;
return str;
}
Implementing ofstream& operator<<:
ofstream& operator<<(ofstream& str, const ThreeD& t) {
str << t.ht << " " << t.wid << " " << t.dep;
return str;
}
Implementing ifstream& operator>>:
ifstream& operator>>(ifstream& str, ThreeD& t) {
str >> t.ht >> t.wid >> t.dep;
return str;
}
Complete Code:
//Operator Overloading
#include <iostream> //console cin cout
#include <fstream> //i/o for file
using namespace std;
class ThreeD {
public:
int ht;
int wid;
int dep;
ThreeD() { ht = wid = dep = 0; }//default
ThreeD(int i, int j, int k) : ht(i), wid(j), dep(k) {}
int getVol() { return ht * wid * dep; }
ThreeD operator+(ThreeD t);
ThreeD operator*(ThreeD t);
ThreeD operator++();//prefix
ThreeD operator++(int neverUsed); //postfix
int& operator[](int k);
friend ostream& operator<<(ostream& str, const ThreeD t);
friend istream& operator>>(istream& str, ThreeD& t);
};
ThreeD ThreeD::operator++() {//prefix
++ht;
++wid;
++dep;
return *this;//this is a pointer pointing to the current object
}
ThreeD ThreeD::operator++(int neverUsed) {//postfix
//return by value
ThreeD temp = *this;
ht++;
wid++;
dep++;
return temp;
}
int& ThreeD::operator[](int k) {//return by ref
//The origianl object will be returned to the calling function.
//No extra copying effort is needed. It is faster than return by value,
//which requires an extra copy to be created and returned to the calling function.
//Because an object is returned, rather than a value, the function can appear
//on the left side of an statement.
switch (k) {
case 0: return ht; //ht will be directly used in calling function
case 1:return wid;
case 2:return dep;
}
}
ThreeD ThreeD::operator+(ThreeD t) {
ThreeD temp;
temp.ht = ht;
temp.wid = t.wid;
temp.dep = dep + t.dep;
return temp;
}
ThreeD ThreeD::operator*(ThreeD t) {
ThreeD temp;
temp.ht = ht * t.ht;
temp.wid = wid * t.wid;
temp.dep = dep * t.dep;
return temp;
}
ostream& operator<<(ostream& str, const ThreeD t) {
str << "[" << t.ht << ", " << t.wid << ", " << t.dep << "]";
return str;
}
istream& operator>>(istream& str, ThreeD& t) {
str >> t.ht >> t.wid >> t.dep;
return str;
}
ofstream& operator<<(ofstream& str, const ThreeD& t) {
str << t.ht << " " << t.wid << " " << t.dep;
return str;
}
ifstream& operator>>(ifstream& str, ThreeD& t) {
str >> t.ht >> t.wid >> t.dep;
return str;
}
int main() {
ThreeD t1(3, 4, 5), t2(10, 11, 12), t3, t4, t5, t6;
int i1{ 10 }, i2{ 20 }, i3;
i3 = i1 + i2;
t3 = t1 + t2; //Will be converted to
//t3 = t1.operator+(t2);
t4 = t1 * t2;
t5 = ++t2;//prefix
t6 = t1++;//postfix
t1[2] = 100;//return by reference allows the function
//to appear on the left side of a statement.
cout << t1[2] << endl;
cout << t1 << endl;
cin >> t4;
cout << t4 << endl;
ofstream out("data1.txt");
out << t1 << endl;
out.close();
ifstream in("data1.txt");
in >> t1;
cout << t1 << endl;
in.close();
return 0;
}