Exceptions:

b

Exceptions Basics

b

Standard Exceptions

b

Custom Exceptions

b

Exception Catching Order

Files:

b

Writing Text Files

b

Reading Text Files

b

Parsing Text Files

b

Structs and Padding

b

Reading and Writing Binary Files

The Standard Template Library:

b

Vectors

b

Vectors and Memory

b

Two-Dimensional Vectors

b

Lists

b

Maps

b

Custom Objects as Map Values

b

Custom Objects as Map Keys

b

Multimaps

b

Sets

b

Stacks and Queues

b

Sorting Vectors, Deque and Friend

b

STL Complex Data Types

Operator Overloading:

b

Overloading the Assignment Operator

b

Printing - Overloading the Left Bit Shift

b

A Complex Number Class

b

Complex.cpp

b

Complex.h

b

Overloading Plus

b

Complex.cpp

b

Complex.h

b

Overloading the Comparison Operator

b

Complex.cpp

b

Complex.h

b

Overloading the Dereference Operator

b

Complex.cpp

b

Complex.h

Output:

string error message: Something else went wrong.
Still running

Exception Basics:

#include <iostream>
#include <string>

using namespace std;

void mightGoWrong()
{
   bool error1 = false;
   bool error2 = true;

   if (error1)
      throw “Something went wrong.”;

   if (error2)
      throw string(“Something else went wrong.”);
}

void usesMightGoWrong()
{
   mightGoWrong();
}

int main()
{
   try
   {
      usesMightGoWrong();
   }
   catch(int e)
   {
      cout << “Error code: ” << e << endl;
   }
   catch(char const* e)
   {
      cout << “Error message: ” << e << endl;
   }
   catch(string& e)
   {
      cout << “string error message: ” << e << endl;
   }

   cout << “Still running” << endl;

   return 0;
}

Output:

Caught exception: vector<T> too long
Still running

Standard Exceptions:

#include <iostream>
#include <vector>
#include <exception>
using namespace std;
int main()
{
   try
   {
      auto v = vector<int>(-1);
   }
   catch (std::exception& e)
   {
      cout << “Caught exception: ” << e.what() << endl;
   }
   cout << “Still running” << endl;
   getchar();
   return 0;
}

 

Output:

Something bad happened!

Custom Exceptions:

#include <iostream>
#include <exception>

using namespace std;

class MyException : public exception
{
public:
   virtual const char* what() const throw()
   {
      return “Something bad happened!”;
   }
};

class Test
{
public:
   void goesWrong()
   {
      throw MyException();
   }
};

int main()
{
   Test test;

   try
   {
      test.goesWrong();
   }
   catch(MyException& e)
   {
      cout << e.what() << endl;
   }

   return 0;
}

Output:

Catching bad_alloc: bad allocation

Exception Catching Order:

#include <iostream>
#include <exception>

using namespace std;

void goesWrong()
{
   bool error1Detected = true;
   bool error2Detected = false;

   if (error1Detected)
      throw bad_alloc();

   if (error2Detected)
      throw exception();
}

int main()
{
   try
   {
      goesWrong();
   }
   catch (bad_alloc& e)
   {
      cout << “Catching bad_alloc: ” << e.what() << endl;
   }
   catch (exception& e)
   {
      cout << “Catching exception: ” << e.what() << endl;
   }

   return 0;
}

Output:

Hello there
123

Writing Text Files:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
   // ofstream outFile;

   fstream outFile;

   string outputFileName = “text.txt”;

   // outFile.open(outputFileName);
   outFile.open(outputFileName, ios::out);

   if (outFile.is_open())
   {
      outFile << “Hello there” << endl;
      outFile << 123 << endl;
      outFile.close();
   }
   else
      cout << “Could not create file: ” << outputFileName << endl;

   return 0;
}

Output:

This is a line.
This is another line.
This is a third line.

Reading Text Files:

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

int main()
{
   string inFileName = “test.txt”;

   ifstream inFile;
   inFile.open(inFileName);

   if (inFile.is_open())
   {
      string line;

      while(inFile)
      {
         getline(inFile, line);
         cout << line << endl;
      }

      inFile.close();
   }
   else
      cout << “Cannot open file: ” << inFileName << endl;

   return 0;
}

Output:

‘Population UK’ — ‘64000000’
‘Population France’ — ‘66400000’

Parsing Text Files:

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

int main()
{
   string filename = “stats.txt”;
   ifstream input;
   input.open(filename);

   if (!input.is_open())
      return 1;

   while(input)
   {
      string line;
      getline(input, line, ‘:’);

      int population;
      input >> population;

      // input.get();
      input >> ws;

      if (!input)
         break;

      cout << “‘” << line << “‘” << ” — ‘” << population << “‘” << endl;
   }

   input.close();

   return 0;
}

Output:

size of struct Person1: 64
size of struct Person2: 62

Structs and Padding:

#include <iostream>
#include <fstream>
using namespace std;
#pragma pack(push, 1)
struct Person
{
   char name[50];
   int age;
   double weight;
};
#pragma pack(pop)
int main()
 {
   cout << sizeof(Person) << endl;
   return 0;
}

Output:

Frodo, 220, 0.8

Reading and Writing Binary Files:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

#pragma pack(push, 1)

struct Person
{
   char name[50];
   int age;
   double height;
};

#pragma pack(pop)

int main()
{
   Person someone = {“Frodo”, 220, 0.8};

   string fileName = “test.bin”;

   //// Write binary file ////////////////
   ofstream outputFile;
   outputFile.open(fileName, ios::binary);

   if (outputFile.is_open())
   {
      outputFile.write(reinterpret_cast<char*>(&someone), sizeof(Person));
      outputFile.close();
   }
   else
      cout << “Could not create file ” + fileName;

   //// Read binary file ////////////////
   Person someoneElse = {};

   ifstream inputFile;
   inputFile.open(fileName, ios::binary);

   if (inputFile.is_open())
   {
      inputFile.read(reinterpret_cast<char*>(&someoneElse), sizeof(Person));
      inputFile.close();
   }
   else
      cout << “Could not read file ” + fileName;

   cout << someoneElse.name << “, ” << someoneElse.age << “, ” << someoneElse.height << endl;

   return 0;
}

 

Output:

For loop:
onr
two
three

Iterator Loop:
one
two
three

Single item.
three

Vectors:

#include <iostream>
#include <vector>
#include <string>
 
using namespace std;
int main()
{
   vector<string> strings;
   strings.push_back(“one”);
   strings.push_back(“two”);
   strings.push_back(“three”);
   cout << “For loop: ” << endl;
   for (int i = 0; i < strings.size(); i++)
      cout << strings[i] << endl;
   cout << endl;
   cout << “Iterator loop: ” << endl;
   for (auto it = strings.begin(); it != strings.end(); ++it)
      cout << *it << endl;
   cout << endl;
   cout << “Single item.” << endl;
   vector<string>::iterator it = strings.begin();
   it += 2;
   cout << *it << endl;
   return 0;
}

Output:

Size: 0
Capacity: 0
Capacity: 1
Capacity: 2
Capacity: 3
Capacity: 4
Capacity: 6
Capacity: 9
Capacity: 13
Capacity: 19
Capacity: 28
Capacity: 42
Capacity: 63
Capacity: 94
Capacity: 141
Capacity: 211
Capacity: 316
Capacity: 474
Capacity: 711
Capacity: 1066
Capacity: 1599
Capacity: 2398
Capacity: 3597
Capacity: 5395
Capacity: 8092
Capacity: 12138
2
Size: 10000
Capacity: 100000

Vectors and Memory:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
   vector<double> numbers(0);
   cout << “Size: ” << numbers.size() << endl;

   int capacity = numbers.capacity();
   cout << “Capacity: ” << capacity << endl;

   for (int i = 0; i < 10000; i++)
   {
      if (numbers.capacity() != capacity)
      {
         capacity = numbers.capacity();
         cout << “Capacity: ” << capacity << endl;
      }

      numbers.push_back(i);
   }

   numbers.reserve(100000);
   cout << numbers[2] << endl;
   cout << “Size: ” << numbers.size() << endl;
   cout << “Capacity: ” << numbers.capacity() << endl;

   return 0;
}

Output:

7777
77778
7777

Two-Dimensional Vectors:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
   vector<vector<int>> grid(3, vector<int>(4, 7));
   grid[1].push_back(8);

   for (int row=0; row < grid.size(); row++)
   {
      for (int col=0; col < grid[row].size(); col++)
         cout << grid[row][col] << flush;

      cout << endl;
   }

   return 0;
}

Output:

Element: 1
Element: 1
0
1
2
3

Lists:

#include <iostream>
#include <list>

using namespace std;

int main()
{
   list<int> numbers;
   numbers.push_back(1);
   numbers.push_back(2);
   numbers.push_back(3);
   numbers.push_front(0);

   list<int>::iterator it = numbers.begin();
   it++;
   numbers.insert(it, 100);
   cout << “Element: ” << *it << endl;

   list<int>::iterator eraseIt = numbers.begin();
   eraseIt++;
   eraseIt = numbers.erase(eraseIt);
   cout << “Element: ” << *eraseIt << endl;

   for (list<int>::iterator it = numbers.begin(); it != numbers.end(); it++)
      cout << *it << endl;

   return 0;
}

Output:

Found Vicky
Mike: 70
Peter: 100
Raj: 20
Vicky: 30
Mike: 70
Peter: 100
Raj: 20
Vicky: 30

Maps:

#include <iostream>
#include <map>
#include <string>

using namespace std;

int main()
{
   map<string, int> ages;
   ages[“Mike”] = 40;
   ages[“Raj”] = 20;
   ages[“Vicky”] = 30;

   ages[“Mike”] = 70;

   ages.insert(make_pair(“Peter”, 100));

   cout << ages[“Raj”] << endl;

   if (ages.find(“Vicky”) != ages.end())
      cout << “Found Vicky” << endl;
   else
      cout << “Key not found.” << endl;

   for (map<string, int>::iterator it = ages.begin(); it != ages.end(); it++)
   {
      pair<string, int> age = *it;
      cout << age.first << “: ” << age.second << endl;
   }

   for (map<string, int>::iterator it = ages.begin(); it != ages.end(); it++)
      cout << it->first << “: ” << it->second << endl;

   return 0;
}

Output:

Copy constructor running!
Copy constructor running!
Copy constructor running!
Copy constructor running!
1: Raj: 20
32: Vicky: 30
50: Mike: 40
55: Bob: 45

Custom Objects as Map Values:

#include <iostream>
#include <map>
#include <string>

using namespace std;

class Person
{
private:
   string name;
   int age;

public:
   Person() : name(“”), age(0)
   {
   }

   Person(string name, int age) : name(name), age(age)
   {
   }

   Person(const Person& other)
   {
      cout << “Copy constructor running!” << endl;

      name = other.name;
      age = other.age;
   }

   void print()
   {
      cout << name << “: ” << age << endl;
   }
};

int main()
{
   map<int, Person> people;
   people[50] = Person(“Mike”, 40);
   people[32] = Person(“Vicky”, 30);
   people[1] = Person(“Raj”, 20);

   people.insert(make_pair(55, Person(“Bob”, 45 )));
   people.insert(make_pair(55, Person(“Sue”, 24 )));

   for (map<int, Person>::iterator it = people.begin(); it != people.end(); it++)
   {
      cout << it->first << “: ” << flush;
      it->second.print();
   }

   return 0;
}

Output:

40: Mike: 40
123: Mike: 444
20: Raj: 40
30: Sue: 30

Custom Objects as Map Keys:

using namespace std;

class Person
{
private:
   string name;
   int age;

public:
   Person() : name(“”), age(0)
   {
   }

   Person(string name, int age) : name(name), age(age)
   {
   }

   Person(const Person& other)
   {
      name = other.name;
      age = other.age;
   }

   void print() const
   {
      cout << name << “: ” << age << flush;
   }

   bool operator<(const Person& other) const
   {
      if (name == other.name)
         return age < other.age;
      else
         return name < other.name;
   }
};

int main()
{
   map<Person, int> people;
   people[Person(“Mike”, 40)] = 40;
   people[Person(“Mike”, 444)] = 123;
   people[Person(“Sue”, 30)] = 30;
   people[Person(“Raj”, 40)] = 20;

   for (map<Person, int>::iterator it = people.begin(); it != people.end(); it++)
   {
      cout << it->second << “: ” << flush;
      it->first.print();
      cout << endl;
   }

   return 0;
}

Output:

10: Vicky
20: Bob
30: Mike
30: Raj

Multimaps:

#include <iostream>
#include <map>
using namespace std;
int main()
{
   multimap<int, string> lookup;
   lookup.insert(make_pair(30, “Mike”));
   lookup.insert(make_pair(10, “Vicky”));
   lookup.insert(make_pair(30, “Raj”));
   lookup.insert(make_pair(20, “Bob”));
   for (multimap<int, string>::iterator it = lookup.begin(); it != lookup.end(); it++)
      cout << it->first << “: ” << it->second << endl;
   cout << endl;
   pair<multimap<int, string>::iterator, multimap<int, string>::iterator> its = lookup.equal_range(3);
   for (multimap<int, string>::iterator it = its.first; it != its.second; it++)
      cout << it->first << “: ” << it->second << endl;
   cout << endl;
   auto its2 = lookup.equal_range(30);
   for (multimap<int, string>::iterator it = its2.first; it != its2.second; it++)
      cout << it->first << “: ” << it->second << endl;
   return 0;
}

Output:

10
20
30
Number found.
10:
20:
30:
333:

Sets:

#include <iostream>
#include <set>
using namespace std;
class Test
{
private:
   int id;
   string name;
public:
   Test(int id, string name) : id(id), name(name)
   {
   }
   bool operator<(const Test& other) const // required for the set to auto sort the Test objects
   {
      if (id < other.id)
         return true;
      return false;
   }
   void print()
   {
      cout << id << “: ” << endl;
   }
};
int main()
{
   set<int> numbers;
   numbers.insert(30);
   numbers.insert(10);
   numbers.insert(30);
   numbers.insert(20);
   for (set<int>::iterator it = numbers.begin(); it != numbers.end(); it++)
      cout << *it << endl;
   set<int>::iterator itFind = numbers.find(30);
   if (itFind != numbers.end())
      cout << “Number found.” << endl;
   set<Test> tests;
   tests.insert(Test(10, “Mike”));
   tests.insert(Test(30, “Joe”));
   tests.insert(Test(333, “Joe”));
   tests.insert(Test(20, “Sue”));
   for (set<Test>::iterator it = tests.begin(); it != tests.end(); it++)
      it->print();
   return 0;
}

Output:

Sue
John

Sue
Mike
John
Sue

Stacks and Queues:

#include <iostream>
#include <string>
#include <stack>
#include <queue>
using namespace std;
class Test
{
   string name;
public:
   explicit Test(string name) : name(name)
   {
   }
   ~Test()
   {
   }
   void print() const
   {
      cout << name << endl;
   }
};
int main()
{
   // LIFO
   stack<Test> testStack;
   testStack.push(Test(“Mike”));
   testStack.push(Test(“John”));
   testStack.push(Test(“Sue”));
   Test& test1 = testStack.top();
   test1.print();
   testStack.pop();
   Test& test2 = testStack.top();
   test2.print();
   // FIFO
   queue<Test> testQueue;
   testQueue.push(Test(“Mike”));
   testQueue.push(Test(“John”));
   testQueue.push(Test(“Sue”));
   cout << endl;
   testQueue.back().print();
   while (testQueue.size() > 0)
   {
      Test& test = testQueue.front();
      test.print();
      testQueue.pop();
   }
   return 0;
}

Output:

5: Mike
7: Raj
10: Sue
3: Vicky

Soting Vectors, Deque and Friend:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Test
{
   string name;
   int id;
public:
   Test(int id, string name) : id(id), name(name)
   {
   }
   bool operator<(const Test& other) const
   {
      return name == other.name ? id < other.id : name < other.name;
   }
   void print()
   {
      cout << id << “: ” << name << endl;
   }
   friend bool comp(const Test& first, const Test& second);
};
bool comp(const Test& first, const Test& second)
{
   return first.name < second.name;
}
int main()
{
   vector<Test> tests;
   tests.push_back(Test(5, “Mike”));
   tests.push_back(Test(10, “Sue”));
   tests.push_back(Test(7, “Raj”));
   tests.push_back(Test(3, “Vicky”));
   sort(tests.begin(), tests.end(), comp);
   for (int i = 0; i < tests.size(); i++)
      tests[i].print();
   return 0;
}

Output:

Mike: 10 20
Vicky: 15

STL Complex Data Types:

#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
int main()
{
   map<string, vector<int>> scores;
   scores[“Mike”].push_back(10);
   scores[“Mike”].push_back(20);
   scores[“Vicky”].push_back(15);
   for (map<string, vector<int> >::iterator it = scores.begin(); it != scores.end(); it++)
   {
      string name = it->first;
      vector<int> scoreList = it->second;
      cout << name << “: ” << flush;
      for (int i = 0; i < scoreList.size(); i++)
         cout << scoreList[i] << ” ” << flush;
      cout << endl;
   }
   return 0;
}

Output:

Print test1: 10: Mike
Assignment running
Print test2: 10: Mike
Assignment running
Print test3: 10: Mike

Copy constructor running
10: Mike

Overloading the Assignment Operator:

#include <iostream>
#include <string>
using namespace std;
class Test
{
   int id; 
   string name;
public:
   Test() : id(0), name(“”)
   {
   }
   Test(int id, string name) : id(id), name(name)
   {
   }
   Test(const Test& other)
   {
      cout << “Copy constructor running” << endl;
      this->id = other.id;
      this->name = other.name;
   }
   const Test& operator=(const Test& other)
   {
      cout << “Assignment running” << endl;
      this->id = other.id;
      this->name = other.name;
      return *this;
   }
   void print() const
   {
      cout << id << “: ” << name << endl;
   }
};
int main()
{
   Test test1(10, “Mike”);
   cout << “Print test1: ” << flush;
   test1.print();
   Test test2(20, “Bob”);
   test2 = test1;
   cout << “Print test2: ” << flush;
   test2.print();
   Test test3;
   test3 = test2;
   cout << “Print test3: ” << flush;
   test3.print();
   cout << endl;
   // Copy initialization.
   Test test4 = test1;
   test4.print();
   return 0;
}

Output:

(2,3): (2,3)

Printing – Overloading the Left Bit Shift:

#include <iostream>
#include <string>
using namespace std;
class Test
{
   int id; 
   string name;
public:
   Test() : id(0), name(“”)
   {
   }
   Test(int id, string name) : id(id), name(name)
   {
   }
   Test(const Test& other)
   {
      this->id = other.id;
      this->name = other.name;
   }
   const Test& operator=(const Test& other)
   {
      this->id = other.id;
      this->name = other.name;
      return *this;
   }
   friend ostream& operator<<(ostream& os, const Test& object)
   {
      os << object.id << “: ” << object.name;
      return os;
   }
};
int main()
{
   Test test1(10, “Mike”);
   cout << test1 << endl;
   return 0;
}

Output:

(2,3): (2,3)

A Complex Number Class:

#include <iostream>
#include “Complex.h”

using namespace std;
using namespace complex;

int main()
{
   Complex c1(2, 3);
   Complex c2(c1);
   Complex c3;

   c3 = c2;

   cout << c2 << “: ” << c3 << endl;

   return 0;
}

Output:

Complex.cpp:

#include “Complex.h”

namespace complex
{
   ostream& operator<<(ostream& out, const Complex& c)
   {
      out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
      return out;
   }

   Complex::Complex() : real(0), imaginary(0)
   {
      // Nothing to do here
   }

   Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
   {
   }

   Complex::Complex(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;
   }

   const Complex& Complex::operator=(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;

      return *this;
   }
} /* namespace complex */

Output:

Complex.h:

#ifndef COMPLEX_H_
#define COMPLEX_H_

#include <iostream>

using namespace std;

namespace complex
{
   class Complex
   {
   private:
      double real;
      double imaginary;

   public:
      Complex();
      Complex(double real, double imaginary);
      Complex(const Complex& other);

      const Complex &operator=(const Complex& other);

      double getReal() const
      {
         return real;
      }

      double getImaginary() const
      {
         return imaginary;
      }
   };

   ostream &operator<<(ostream& out, const Complex& c);
} /* namespace complex */
#endif /* COMPLEX_H_ */

Output:

(3,4)
(10,14)
(11,2)
(4.2,7)
(30,14)

Overloading Plus:

#include <iostream>
#include “Complex.h”

using namespace std;
using namespace complex;

int main()
{
   Complex c1(3, 4);
   Complex c2(2, 3);
   Complex c3 = c1 + c2;

   cout << c1 << endl;
   cout << c1 + c2 + c3 << endl;

   Complex c4(4, 2);
   Complex c5 = c4 + 7;
   cout << c5 << endl;

   Complex c6(1, 7);
   cout << 3.2 + c6 << endl;
   cout << 7 + c1 + c2 + 8 + 9 + c6 << endl;

   return 0;
}

Output:

Complex.cpp:

#include “Complex.h”

namespace complex
{
   ostream& operator<<(ostream& out, const Complex& c)
   {
      out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
      return out;
   }

   Complex operator+(const Complex& c1, const Complex& c2)
   {
      return Complex(c1.getReal() + c2.getReal(), c1.getImaginary() + c2.getImaginary());
   }

   Complex operator+(const Complex& c1, double d)
   {
      return Complex(c1.getReal() + d, c1.getImaginary());
   }

   Complex operator+(double d, const Complex& c1)
   {
      return Complex(c1.getReal() + d, c1.getImaginary());
   }

   Complex::Complex() : real(0), imaginary(0)
   {
      // TODO Auto-generated constructor stub
   }

   Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
   {
   }

   Complex::Complex(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;
   }

   const Complex& Complex::operator=(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;

      return *this;
   }
} /* namespace complex */

Output:

Complex.h:

#ifndef COMPLEX_H_
#define COMPLEX_H_

#include <iostream>

using namespace std;

namespace complex
{
   class Complex
   {
   private:
      double real;
      double imaginary;

   public:
      Complex();
      Complex(double real, double imaginary);
      Complex(const Complex& other);

      const Complex& operator=(const Complex& other);

      double getReal() const
      {
         return real;
      }

      double getImaginary() const
      {
         return imaginary;
      }
   };

   ostream& operator<<(ostream& out, const Complex& c);
   Complex operator+(const Complex& c1, const Complex& c2);
   Complex operator+(const Complex& c1, double d);
   Complex operator+(double d, const Complex& c1);
} /* namespace complex */
#endif /* COMPLEX_H_ */

Output:

Not equal
Not equal

Overloading the Comparison Operator:

#include <iostream>
#include “Complex.h”

using namespace std;
using namespace complex;

int main()
{
   Complex c1(3, 2);
   Complex c2(3, 3);

   if (c1 == c2)
   {
      cout << “Equal” << endl;
   }
   else
   {
      cout << “Not equal” << endl;
   }

   if (c1 != c2)
   {
      cout << “Not equal” << endl;
   }
   else
   {
      cout << “Equal” << endl;
   }

   return 0;
}

Output:

Complex.cpp:

#include “Complex.h”

namespace complex
{
   ostream& operator<<(ostream& out, const Complex& c)
   {
      out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
      return out;
   }

   Complex operator+(const Complex& c1, const Complex& c2)
   {
      return Complex(c1.getReal() + c2.getReal(), c1.getImaginary() + c2.getImaginary());
   }

   Complex operator+(const Complex& c1, double d)
   {
      return Complex(c1.getReal() + d, c1.getImaginary());
   }

   Complex operator+(double d, const Complex& c1)
   {
      return Complex(c1.getReal() + d, c1.getImaginary());
   }

   Complex::Complex() : real(0), imaginary(0)
   {
      // TODO Auto-generated constructor stub
   }

   Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
   {
   }

   Complex::Complex(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;
   }

   const Complex& Complex::operator=(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;

      return *this;
   }

   bool Complex::operator==(const Complex& other) const
   {
      return (real == other.real) && (imaginary == other.imaginary);
   }

   bool Complex::operator!=(const Complex& other) const
   {
      return !(*this==other);
   }
} /* namespace complex */

Output:

Complex.h:

#ifndef COMPLEX_H_
#define COMPLEX_H_

#include <iostream>

using namespace std;

namespace complex
{
   class Complex
   {
   private:
      double real;
      double imaginary;

   public:
      Complex();
      Complex(double real, double imaginary);
      Complex(const Complex& other);

      const Complex &operator=(const Complex& other);

      double getReal() const
      {
         return real;
      }

      double getImaginary() const
      {
         return imaginary;
      }

      bool operator==(const Complex& other) const;
      bool operator!=(const Complex& other) const;
   };

   ostream &operator<<(ostream& out, const Complex& c);
   Complex operator+(const Complex& c1, const Complex& c2);
   Complex operator+(const Complex& c1, double d);
   Complex operator+(double d, const Complex& c1);
} /* namespace complex */
#endif /* COMPLEX_H_ */

Output:

(6,-7)

Overloading the Dereference Operator:

#include <iostream>
#include “Complex.h”

using namespace std;
using namespace complex;

int main()
{
   Complex c1(2, 4);

   cout << *c1 + *Complex(4, 3) << endl;

   return 0;
}

Output:

Complex.cpp:

#include “Complex.h”

namespace complex
{
   ostream& operator<<(ostream& out, const Complex& c)
   {
      out << “(” << c.getReal() << “,” << c.getImaginary() << “)”;
      return out;
   }

   Complex operator+(const Complex& c1, const Complex& c2)
   {
      return Complex(c1.getReal() + c2.getReal(), c1.getImaginary() + c2.getImaginary());
   }

   Complex operator+(const Complex& c1, double d)
   {
      return Complex(c1.getReal() + d, c1.getImaginary());
   }

   Complex operator+(double d, const Complex& c1)
   {
      return Complex(c1.getReal() + d, c1.getImaginary());
   }

   Complex Complex::operator*() const
   {
      return Complex(real, -imaginary);
   }

   Complex::Complex() : real(0), imaginary(0)
   {
   }

   Complex::Complex(double real, double imaginary) : real(real), imaginary(imaginary)
   {
   }

   Complex::Complex(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;
   }

   const Complex& Complex::operator=(const Complex& other)
   {
      real = other.real;
      imaginary = other.imaginary;

      return *this;
   }

   bool Complex::operator==(const Complex& other) const
   {
      return (real == other.real) && (imaginary == other.imaginary);
   }

   bool Complex::operator!=(const Complex& other) const
   {
      return !(*this==other);
   }
} /* namespace complex */

Output:

Complex.h:

#ifndef COMPLEX_H_
#define COMPLEX_H_

#include <iostream>

using namespace std;

namespace complex
{
   class Complex
   {
   private:
      double real;
      double imaginary;

   public:
      Complex();
      Complex(double real, double imaginary);
      Complex(const Complex &other);

      const Complex &operator=(const Complex &other);

      double getReal() const
      {
         return real;
      }

      double getImaginary() const
      {
         return imaginary;
      }

      bool operator==(const Complex &other) const;
      bool operator!=(const Complex &other) const;
      Complex operator*() const;
   };

   ostream& operator<<(ostream& out, const Complex& c);
   Complex operator+(const Complex& c1, const Complex& c2);
   Complex operator+(const Complex& c1, double d);
   Complex operator+(double d, const Complex& c1);
} /* namespace complex */
#endif /* COMPLEX_H_ */