C++ Tidbits – Inheritance

I am about to complete a course on Neural Networks and Deep Learning. I am amazed at how one gets absorbed into the subject and language (in this case Python). Lately when I am working with C, C++, Java or Python I occasionally use a syntax from a different language.

In this post I will be covering / reviewing Inheritance using C++. Many years ago when I wanted to review C I would pull from my bookshelf the book “C Programming Language” by Brian Kernighan and Dennis Ritchie. During the years I have owned several copies. A few minutes ago I tried to locate my latest copy, but it seems that it grew legs and walked away. For C++ I have … (I guess I have also misplaced it) a book by Bjarne Stroustrup. Given the fact that I want a quick refresher, decided to go over an Advanced C++ Programming course by Mike McMillan. For this post (and a few more that I will write in the next few days) I am using this course as a guide and will be coding C++ on Visual Studio 2017 from Microsoft.

In a nutshell inheritance in any object oriented programming language helps us derive new classes which inherit from a base class. Some languages support inheritance from a single class while others allow us to inherit from multiple ones. You might want to take a look at the article Inheritance (object-oriented programming) in Wikipedia.

Given that I spent several hours writing the code and experimenting with it, and did not take notes, I will present the materials starting with a screen capture of the console output generated by the main program.

main <<< emp1: firstName:James lastName: Bond employeeID: 7 payRate: 200000.000000
main <<< emp2: firstName:John lastName: Canessa employeeID: 1234 payRate: 150000.000000
main <<< emp2: firstName:John lastName: Canessa employeeID: 1234 payRate: 150000

main <<<           emp3: Mary Smith 15
main <<< emp3 gross pay: 600

main <<<            emp4: Bob Brown 1500
main <<< emp4 isSalaried: 1
main <<<  emp4 gross pay: 1500

main <<<            emp4: firstName: Bob lastName: Brown employeeID: 0 payRate: 1500.000000 isSalaried: salaried
main <<<  emp4 gross pay: 1500

main <<< balance: 600
main <<< balance: 549.5

Quad with sides: 3 5 5 2
Quad with sides: 6 6 6 6

What follows is the main program that generated the previous screen capture:

// main.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include "pch.h"
#include <iostream>


int main()
{

	// **** create an employee ****
	Employee emp1 = Employee("James", "Bond", 200000.00);
	emp1.setEmployeeID(007);
	cout << "main <<< emp1: " << emp1.toString() << endl;

	// **** create another employee ****
	Employee emp2 = Employee("John", "Canessa");
	emp2.setEmployeeID(1234);
	emp2.setPayRate(150000.00);
	cout << "main <<< emp2: " << emp2.toString() << endl;
	cout << "main <<< emp2: " << emp2.toString2() << endl << endl;

	// **** create an employee ****
	Employee emp3("Mary", "Smith", 15.00);
	cout << "main <<<           emp3: " << emp3.getFirstName() << " " << emp3.getLastName() << " " << emp3.getPayRate() << endl;
	cout << "main <<< emp3 gross pay: " << emp3.grossPay(40) << endl << endl;

	// **** create a manager ****
	Manager emp4("Bob", "Brown", 1500, true);
	cout << "main <<<            emp4: " << emp4.getFirstName() << " " << emp4.getLastName() << " " << emp4.getPayRate() << endl;
	cout << "main <<< emp4 isSalaried: " << emp4.getIsSalaried() << endl;
	cout << "main <<<  emp4 gross pay: " << emp4.grossPay() << endl << endl;

	cout << "main <<<            emp4: " << emp4.toString() << endl;
	cout << "main <<<  emp4 gross pay: " << emp4.grossPay(999) << endl << endl;
	
	// **** experiment with a checking account ****
	CheckingAccount myAcct(500.00, 0.50);
	myAcct.credit(100.00);
	cout << "main <<< balance: " << myAcct.getBalance() << endl;

	myAcct.debit(50.00);
	cout << "main <<< balance: " << myAcct.getBalance() << endl << endl;

	// **** experiment with a trapezoid and a square ****
	Trapezoid t1(3, 5, 5, 2);
	Square s1(6);
	t1.display();
	s1.display();
}

Each section starts with a comment. We start by creating and displaying three employees. We then create a manager and add some functionality in the process.

The source code for the Employee.h file follows:

#pragma once

using namespace std;

#include <iostream>
#include <string>

// **** our base class ****
class Employee 
{

//private:
protected:
	int		employeeID;
	string	firstName;
	string	middleName;
	string	lastName;

	double	payRate;

public:

	// **** constructors ****
	Employee();

	Employee(string firstName, string lastName);

	Employee(string firstName, string lastName, double payRate);

	// **** destructor ****
	~Employee();

	// **** getters and setters ****
	string getFirstName();
	void setFirstName(string firstName);

	string getLastName();
	void setLastName(string lastName);

	double getPayRate();
	void setPayRate(double payRate);

	int getEmployeeID();
	void setEmployeeID(int employeeID);

	// **** to string ****
	string toString();
	string toString2();

	// **** other methods ****
	double grossPay(int hours);
};

The source code for the Employee class follows:

#include "pch.h"

#include <sstream>

// **** constructor ****
Employee::Employee()
{
	this->firstName		= "";
	this->middleName	= "";
	this->lastName		= "";

	this->employeeID	= 0;
	this->payRate		= 0.0;
}

// **** constructor ****
Employee::Employee(string firstName, string lastName)
{
	this->firstName		= firstName;
	this->middleName	= "";
	this->lastName		= lastName;

	this->employeeID	= 0;
	this->payRate		= 0.0;
}

// **** constructor ****
Employee::Employee(string firstName, string lastName, double payRate)
{
	this->firstName		= firstName;
	this->middleName	= "";
	this->lastName		= lastName;

	this->employeeID	= 0;
	this->payRate		= payRate;
}

// **** destructor ****
Employee::~Employee()
{
	// **** to do: free allocated resources **** 
}

// **** getters and setters ****
string Employee::getFirstName()
{
	return this->firstName;
}

void Employee::setFirstName(string firstName)
{
	this->firstName = firstName;
}

string Employee::getLastName()
{
	return this->lastName;
}

void Employee::setLastName(string lastName)
{
	this->lastName = lastName;
}

double Employee::getPayRate()
{
	return this->payRate;
}

void Employee::setPayRate(double payRate)
{
	this->payRate = payRate;
}

int Employee::getEmployeeID()
{
	return this->employeeID;
}

void Employee::setEmployeeID(int employeeID)
{
	this->employeeID = employeeID;
}

// **** to string ****
string Employee::toString()
{
	return "firstName:" + firstName + " lastName: " + lastName + " employeeID: " + to_string(employeeID) + " payRate: " + to_string(payRate);
}

string Employee::toString2()
{
	stringstream stm;
	stm << "firstName:" << firstName << " lastName: " << lastName << " employeeID: " << employeeID << " payRate: " << payRate; return stm.str(); } // **** other methods **** double Employee::grossPay(int hours) { return this->payRate * hours;
}

We derive the Manager class from the employee class. The header file follows:

#pragma once

using namespace std;

#include <iostream>
#include <string>

// **** our derived class ****
class Manager : public Employee
{

private:
	bool isSalaried;

public:

	// **** constructor(s) ***
	Manager();

	Manager(string firstName, string lastName, double payRate, bool isSalaried);

	// **** destructor ****
	~Manager();

	// **** getter and setters ****
	bool getIsSalaried();
	void setIsSalaried(bool isSalaried);

	// **** other methods ****
	double grossPay();
	double grossPay(int hours);

	// **** to string ****
	string toString();
};

The source file for the Manager class follows:

#include "pch.h"

// **** default constructor ****
Manager::Manager() : isSalaried(true)
{
}

// **** constructor ****
Manager::Manager(string firstName, string lastName, double payRate, bool isSalaried)
	: Employee(firstName, lastName, payRate)			// call to base classed constructor
{
	this->isSalaried = isSalaried;
}

// **** destructor ****
Manager::~Manager()
{
	// **** to do: free allocated resources **** 
}

// **** getters and setters ****
bool Manager::getIsSalaried()
{
	return this->isSalaried;
}

void Manager::setIsSalaried(bool isSalaried)
{
	this->isSalaried = isSalaried;
}

// **** other methods ****
double Manager::grossPay()
{
	return this->payRate;
}

double Manager::grossPay(int hours)
{
	if (isSalaried)
		return this->payRate;
	else
		return this->payRate * hours;
}

// **** to string ****
string Manager::toString()
{
	return "firstName: " + firstName + " lastName: " + lastName + " employeeID: " + to_string(employeeID) + 
			" payRate: " + to_string(payRate) + " isSalaried: " + (isSalaried ? "salaried" : "hourly");
}

The next example is with a checking account. We first create an Account base class and then a derive Checking account class.

#pragma once

using namespace std;

#include <iostream>
#include <string>

// **** our base class ****
class Account
{

protected:
	double balance;

public:

	// **** constructor ****
	Account(double balance);

	// **** destructor ****
	~Account();

	// **** getters and setters ****
	double getBalance();

	// **** other methods ****
	void credit(double amount);

	void debit(double amount);
};

The Account class follows:

#include "pch.h"

// **** constructor ****
Account::Account(double balance)
{
	if (balance > 0.0)
		this->balance = balance;
	else
		this->balance = 0.0;
}

// **** destructor ****
Account::~Account()
{
}

// **** getters and setters ****
double Account::getBalance()
{
	return this->balance;
}

// **** other methods ****
void Account::credit(double amount)
{
		this->balance += amount;
}

void Account::debit(double amount)
{
	if (this->balance > amount)
		this->balance -= amount;
	else
		cout << "Insufficient funds !!!" << endl;
}

The header file for the CheckingAccount class follows:

#pragma once

using namespace std;

#include <iostream>
#include <string>

/// **** our derived class ****
class CheckingAccount : public Account
{
private:
	double fee;

public:
	// **** constructor ***
	CheckingAccount(double balance, double fee);

	// **** destructor ****
	~CheckingAccount();

	// **** other methods ****
	void debit(double amount);
};

The source code for the CheckingAccount class follows:

#include "pch.h"

// **** constructor ****
CheckingAccount::CheckingAccount(double balance, double fee)
	: Account(balance)
{
	if (fee > 0.0)
		this->fee = fee;
}

// **** destructor ****
CheckingAccount::~CheckingAccount()
{
}

// **** other methods ****
void CheckingAccount::debit(double amount)
{
	if (this->balance > amount)
		this->balance -= (amount + this->fee);
	else
		cout << "Insufficient funds !!!" << endl;
}

To make sure the concepts are clear (lots of repetition) we will create a base and two derived classes. In this case the base class is named Quad (short for Quadrilateral) and the derived classes are a Trapezoid and a Square.

#pragma once

using namespace std;

#include <iostream>
#include <string>

// **** base class ****
class Quad
{

protected:
	double side1;
	double side2;
	double side3;
	double side4;

public:

	// **** constructor ****
	Quad(double side1, double side2, double side3, double size4);

	// **** destructor ****
	~Quad();

	// **** other methods ****
	void display();
};

The Quad class source code follows:

#include "pch.h"

// **** constructor ****
Quad::Quad(double side1, double side2, double side3, double side4)
{
	this->side1 = side1;
	this->side2 = side2;
	this->side3 = side3;
	this->side4 = side4;
}

// **** destructor ****
Quad::~Quad()
{
	// **** to do: free allocated resources **** 
}

// **** other methods ****
void Quad::display()
{
	cout << "Quad with sides: " << this->side1 << " " << this->side2 
		<< " " << this->side3 << " " << this->side4 << endl;
}

The Trapezoid class header file follows:

#pragma once

using namespace std;

#include <iostream>
#include <string>

// **** derived class ****
class Trapezoid : public Quad
{
public:

	// **** constructor ****
	Trapezoid(double side1, double side2, double side3, double side4);

	// **** destructor ****
	~Trapezoid();
};

The Trapezoid class source code follows:

#include "pch.h"

// **** constructor ****
Trapezoid::Trapezoid(double side1, double side2, double side3, double side4)
	: Quad(side1, side2, side3, side4)			// call to base classed constructor
{
}

// **** destructor ****
Trapezoid::~Trapezoid()
{
	// **** to do: free allocated resources **** 
}

The Square class header file:

#pragma once

using namespace std;

#include <iostream>
#include <string>

// **** derived class ****
class Square : public Quad
{
public:

	// **** constructor ****
	Square(double side);

	// **** destructor ****
	~Square();
};

The Square class source code:

#include "pch.h"

// **** constructor ****
Square::Square(double side)
	: Quad(side, side, side, side)
{
}

// **** destructor ****
Square::~Square()
{
	// **** to do: free allocated resources **** 
}

The actual code is not something too exciting, but repeating and enhancing code helps bring back concepts and syntax.

If you have comments or questions regarding this or any other post please leave me a note.

Happy software development;

John

Follow me on Twitter:  @john_canessa

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.