Function Templates

By adding template to the function definition, we can turn a function into a generic function. Absolute value is a good example of a generic function that can take multiple data types.

template <class T>
T absValue(T x){
    if(x < 0){
        return -x;
    }
    return x;
}


int main()
{
    int x = 2563;
    int y = -2914;
    int z = 47.5432;

    cout << "The absolute value of " << x << " is " << absValue(x) << endl;

    cout << "The absolute value of " << y << " is " << absValue(y) << endl;

    cout << "The absolute value of " << z << " is " << absValue(z) << endl;

    return 0;
}

Whenever we see T in a C++ program, chances are we are looking at a template. The use of T as a template parameter name is simply a convention.

When writing templates the problem is that we do not know what type or types T will actually be. So the function must be generic.

If a template takes multiple arguments, we should separate the arguments with a comma.

//returns a negative value if x is less than y
//0 if x and y are roughly the same
//a positive number if x is greater than y
template <class T, class U>
int compareValues(T x, U y){
    double rValue = x - y;
    double cValue = rValue;

    if(cValue < 0){
        cValue *= -1;
    }

    if(cValue < .000000001){
        return 0;
    }
    return rValue;
}

int main()
{
   int x = 47;
   double y = 19.99;
   char z = 's';

   if(compareValues(x, y) < 0){
    cout << x << " is greater than " << y << endl;
   } else {
    cout << y << " is greater than " << x << endl;
   }

   if(compareValues(y, z) < 0){
    cout << y << " is less than " << z << endl;
   } else {
    cout << y << " is greater than " << z << endl;
   }

    return 0;
}

C++ Classes

A class is a derived type where the elements are other types, including functions and operators. An object is an instantiation of a class allocated in memory; it is a self-contained unit that has its own state and is able to access its member functions.

Let’s create a class to deal with rational numbers.

class Rational {

public:
	void assign(int n, int d);
	double convert();
	void invert();
	void print();

private:
	int _num, _denom;

};

A class declaration begins with the keyword

class

followed by the name of of the class. The functions within the class definition are called member functions; the variables are called member data. Typically member data is defined as being private, meaning they cannot be accessed directly.

The class is defined in a header file, and implemented in a separate file.

#include "Rational.h"

#include <iostream>

void Rational::assign(int n, int d) {
	_num = n;
	_denom = d;
}

double Rational::convert() {
	return (double)_num / _denom;
}

void Rational::invert() {
	int temp = _num;
	_num = _denom;
	_denom = temp;
}

void Rational::print() {
	std::cout << _num << '/' << _denom;
}

Usually we define the class methods outside the class declaration, using the scope resolution operator :: to indicate which class the methods are members of. This separates the declarations from their definitions, which is consistent with the principle of information hiding.

The rational class we have created has a member function called assign() to assign values to its member variables. Often, it is good to establish the object’s state when it is declared. We can do this using the class constructor. The constructor function allows us to initialize the object automatically when it is declared.

A constructor function has the same name as the class itself and is declared without a return type.

Rational::Rational(int n, int d) {
	_num = n;
	_denom = d;
}

A class’s member variables are usually declared private to limit access; however, it is also common to include public methods that provide screened access to the data. These access functions are also called getters and setters; getter functions allow us to read the value and setter functions allow us to set the value.

int Rational::numerator() {
	return _num;
}

int Rational::denominator() {
	return _denom;
}

Typically member variables are private and methods are public. It is also useful though to have some private methods as well. These methods can only be called from other methods within the class, as such they are usually utility functions.

Every class has at least two constructors. In addition to the default constructor, there is also a copy constructor. The copy constructor is called whenever an object is copied.

Rational::Rational(const Rational& rObj) { 
      this->_num = rObj._num; 
      this->_denom = rObj._denom; 
}

The copy constructor is called automatically whenever an object is copied by means of a declaration initialization, whenever an object is passed by value to a function, and whenever an object is returned by value from a function.

With classes, it is also possible to overload operators. The assignment operator is the operator most often overloaded. The purpose of the assignment operator is to copy one object to another. The assignment operator is created automatically for every class that is defined, but it can be defined explicitly in the class definition.

Rational& operator=(const Rational& r);

The name of the member function is operator=. Its argument list is the same as that of the copy constructor, it has a constant reference to an object of the same class.

Rational& Rational::operator =(const Rational& rObj) {
	_num = rObj._num;
	_denom = rObj._denom;
	return *this;
}

Search Algorithms in C++

A frequent requirement for many programs is to search a list for a given item. The two most common basic methods of searches are sequential searches and binary searches.

In a sequential search, each item in a list is examined in the order in which it occurs in the list until the desired item is found or the end of the list is reached. The main advantage to a linear sort is that the list does not need to be sorted before searching. The main disadvantage is that it is an inefficient search.

Essentially,  a linear search says For all the items in the list, compare the item to the desired value. If the value is found, return the location of the item. Otherwise, return a flag value indicating that the item was not found.

using namespace std;

//returns -1 if the value is not found
int linearSearch(int list[], int bounds, int searchValue);
void displaySearchValue(int theList[], int index);

int main(){
    int theList[] = { 4, 8, 15, 16, 23,  24, 3, 5, 17, 257};
    int bounds =  sizeof(theList) / sizeof(int);

    int searchValue = 10;
    int rValue = linearSearch(theList, bounds, searchValue);
    displaySearchValue(theList, rValue);

    searchValue = 5;
    rValue = linearSearch(theList, bounds, searchValue);
    displaySearchValue(theList, rValue);

    return 0;
}


void displaySearchValue(int theList[], int index){
    if(index < 0){
        cout << "The value was not found" << endl;
    } else {
        cout << "The value was found at [" << index << "] and is " << theList[index] << endl;
    }

}
int linearSearch(int list[], int bounds, int searchValue){
    //go backwards through the array to find the value
    for(int i = bounds; i > -1; i--){
        if(list[i]==searchValue){
            return i;
        }
    }
    //return a negative value;
    return -1;
}

As has already been mentioned, the big advantage to linear searches is that the list does not have to be in sorted order to perform the search. Another advantage is that if the item is found relatively early in the search, then the inefficiency of the searching algorithm is not as big of a concern.

In a binary search, the list is required to be in sorted order. Starting in the middle, we compare the item to the desired value. One of three possible results can come from this comparison – either the desired item is found, or the desired value may be greater or less than the middle value. If the desired item is greater than the middle element, if it is in the list we know it must be in the half that comes after the middle value. Likewise, if the desired item is less than the middle element, we know that the element must be in the half that comes before the middle value.

The binary search algorithm functions be first setting the lower index to 0. It then sets the upper index to one less than the size of the list. We then begin with the first item in the list.  We search while the lower index is less than or equal to the upper index. In this loop, we set the midpoint index to the integer average of the lower and upper index values. We compare the desired key value to the midpoint element. If the element is found, we return the index value of the current item. Otherwise, if the desired element is greater than the midpoint element, we set the lower index value to the midpoint value + 1, since we know the value must be in the range after the midpoint value. If the value is less than the midpoint element, we set the upper index to the midpoint value minus one.

using namespace std;

int binarySearch(int theList[], int bounds, int key);
void displayValue(int theList[], int index);

int main()
{
    int ourValues[] = {1, 2, 3, 4, 5, 8, 15, 16, 17, 23, 32, 42, 64, 128, 404};
    int searchValue = 5;

    int found = binarySearch(ourValues, sizeof(ourValues) / sizeof(int), searchValue);


    displayValue(ourValues, found);

    return 0;
}

void displayValue(int theList[], int index){
    if(index > 0){
        cout << "Value found at index [" << index << "] (" << theList[index] << ")" << endl;
     } else {
        cout << "Value not found" << endl;
     }
}
int binarySearch(int theList[], int bounds, int key){
    int lower, upper, mid;
    lower = 0;
    upper = bounds - 1;

    while(lower <= upper){         mid = (int)((lower + upper) / 2);         
      if(theList[mid]==key){             return mid;         } 
        else if(key > theList[mid]){
            lower = mid + 1;
        } else {
            upper = mid - 1;
        }
    }
    return -1;
}

The great thing about the binary search is that the number of items to search through is halved each time through the search loop. In general, after p passes through the search loop, the number of values remaining to be searched is N / (2 ^ p).

One of the simplest sorting techniques is the selection sort. In a selection sort, the smallest value is initially selected from the complete list of data and switched with the first element on the list. Once the smallest value is sorted, the next pass needs to only consider the second through the last elements.

using namespace std;

void printList(int theList[], int bounds);
void selectionSort(int theList[], int bounds);

int main()
{
    int aList[] = {404, 10538, 3, 5, 17, 257, 451, 80, 443, 1729, 1701, 1138, 47};
    int bounds = sizeof(aList) / sizeof(int);

    printList(aList, bounds);
    selectionSort(aList, bounds);
    printList(aList, bounds);

    return 0;
}

void printList(int theList[], int bounds){
    cout << endl;
    for(int i = 0; i < bounds; i++){
        cout << theList[i] << "\t";
    }
    cout << endl;

}
void selectionSort(int theList[], int bounds){
    int i, total, remaining, smallest, tmp, minimumIndex;
    total = bounds - 1;
    for(i = 0; i < total; i++){
        minimumIndex = i;
        for(remaining = i + 1; remaining < bounds; remaining++){
            if(theList[remaining] < theList[minimumIndex]){
                minimumIndex = remaining;
            }
        }
        //check if anything needs to be moved
        //if so, swap the values;
        if(minimumIndex != i){
            tmp = theList[i];
            theList[i] = theList[minimumIndex];
            theList[minimumIndex] = tmp;
        }
    }


}

Class in C++

A class is a collection of members that can be either variables or functions. Variables in a class are declared as variables elsewhere are; function prototypes are used to declare a function, and they are defined elsewhere. A class function can access any member in a class.

In C++, class is a reserved word. The class definition is contained in curly braces, after which there should be a semi-colon.

Class members are classified in three categories: private, public, and protected. These categories are defined by the reserved words private, public, and protected, which are member access specifiers.

By default, all members of a class are private.

#ifndef LINE_H
#define LINE_H

class Line
{
 public:
 Line();
 void setPointA(int x, int y);
 void setPointB(int x, int y);
 int getPointAX() const;
 int getPointBX() const;
 int getPointAY()const;
 int getPointBY()const;
 double getLength() const;
 private:
 int aX;
 int aY;
 int bX;
 int bY;
};

#endif // LINE_H

The class declaration is usually put into a header file, of type .h. The public methods are used to modify and retrieve these data members. Note that the functions that retrieve data members from the class are declared const, this ensures that these methods will not modify the data members of the function, only retrieve them.

The definition includes only the function prototypes. For these functions to actually work, we need to include the algorithms that the functions are meant to execute. Member function implementations are usually put in a separate file; the scope resolution operator, ::, is used to reference the member functions to their class.

#include <cmath>

Line::Line()
{

}

void Line::setPointA(int x, int y){
    this->aX = x;
    this->aY = y;
}

void Line::setPointB(int x, int y){
   this->bX = x;
   this->bY = y;
}

int Line::getPointAX() const{
    return this->aX;
}

int Line::getPointBX() const{
    return this->bX;
}

int Line::getPointAY()const{
    return this->aY;
}

int Line::getPointBY()const{
    return this->bY;
}

double Line::getLength() const{
    double length = pow(this->bX - this->aX, 2) + pow(this->bY - this->aY, 2);
    return sqrt(length);
}

Once an object of a class is declared, it can access the members of the class using the dot operator, .  The object of a class is limited to accessing the public members of the class, however.

#include "Line.h";

using namespace std;

int main()
{

    Line aLine = Line();
    aLine.setPointA(1, 2);
    aLine.setPointB(4, 6);

    cout << "The length of the line is " << aLine.getLength() << endl;

    return 0;
}

Every class has member functions that only access and do not modify the data members; these methods are called accessor functions. Likewise, every class has member functions that modify the data members, called mutator functions.

 

Structures in C++

Structures are more versatile than arrays because a single structure can store items of more than one data type.

Creating a structure is a two-part process. A structure is a user-definable type, where the structure’s declaration defines the type’s data properties. After the type has been defined, we can create variables of that type.

Unlike in plain vanilla C, C++ allows us to drop the keyword struct when we declare structure variables.

using namespace std;

struct product{
    char name[32];
    double price;
    unsigned int id;
};

int main()
{

    product a;

    product b;


    return 0;
}

Member names in a structure enable us to access members of a structure in the same way that indices enable us to access elements in an array.

Structures are usually declared externally, which means they are placed outside any function. An external declaration can be used by all functions that follow it.

using namespace std;

struct point{
    char name;
    double x;
    double y;
};

int main()
{

    point pA = {'a', 43, 73};
    point pB = {'b', 50, 25};

    cout << pA.name << " (" << pA.x << ", " << pA.y << ") " << endl;

    return 0;
}

It is possible to create arrays of structures; doing so is no different than creating arrays of basic types. In such an array, each element is a structure that can be accessed via its offset. Initializing an array of structures involves taking a brace-enclosed, comma-separated list of values where each value in turn is enclosed with curly braces, and has a comma separated list of values for each structure member.

using namespace std;

struct example{
    double a;
    int b;
    char c;
};

void printArray(example structArray[], int n);

int main()
{

    example structArray[3]{
        {
            19.99, 47, 'c'
        },
        {
            2.718, 1138, 'h'
        },
        {
            1.12358, 8086, 'z'
        }
    };

    printArray(structArray, 3);

    return 0;
}

void printArray(example structArray[], int n){
    int i;
    for(i = 0; i < n; i++){
        cout << structArray[i].a << " " << structArray[i].b << " " << structArray[i].c << endl;
    }
}

 

The Class User Type

A class is a user-defined type with both data and method members. A variable of the class type is called an object. A class’s members are partitioned into three separate access levels, public, private, and protected. The private members of a class can be accessed only by that class’s member functions. The public members of a class can be accessed by any part of the program that has an object of the class in scope. Protected members are in between these two, as they can be accessed by derived classes.

A class declaration describes a new data type. A class declaration begins with the reserved word class followed by the name of the class. The members are then listed in the class body that follows, which is enclosed by curly braces and terminated with a semicolon. The reserved words public and private separate the class into public and private sections. The data members are described in the same manner as variables, and the methods are described as functions.

#ifndef CRECTANGLE_H
#define    CRECTANGLE_H

class CRectangle{

private:
    double _length;
    double _width;
public:
    //constructor
    Rectangle(double length, double width);
    //getters and setters
    double GetLength(void);
    void SetLength(double length);
    double GetWidth(void);
    void SetWidth(double width);
    
    double Perimeter(void);
    double Area(void);

};

#endif    /* CRECTANGLE_H */

The class constructor is the function without a return value that has the same name as the class. A constructor can be passed parameters that are used to initialize the data members of the class. A class declaration does not have to include a constructor. However, supplying one or more class constructors insures that any objects are initialized with the necessary state for executing its methods.

We need to provide a definition for each method in the class declaration. Typically, we want to define these methods outside the class body. We place the class name, followed by a double colon, immediately in front of the class method name. The double colon symbol is called the scope resolution operator, an indicates that the function belongs to the scope of the class.

#include "CRectangle.h"

//constructor
CRectangle::CRectangle(double length, double width)
{
 _length = length;
 _width = width;
}

double CRectangle::GetLength(void)
{
 return _length;
}

void CRectangle::SetLength(double length)
{
 _length = length;
}

double CRectangle::GetWidth(void)
{
 return _width;
}

void CRectangle::SetWidth(double width)
{
 _width = width;
}

double CRectangle::Perimeter(void)
{
 return _width * 2 + _length * 2;
}

Declaring an object of a class type creates an instance of that class. The declaration instantiates an object of the class type and automatically calls the the class constructor. If no class constructor has been explicitly defined, the compiler provides a default constructor.

Objects can be assigned to one another easily. Unless otherwise specified with a customized assignment operator, object assignment is accomplished via a bitwise copy of data members.

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

using namespace std;

int main()
{
 CRectangle rec01(10, 30);
 CRectangle rec02(50, 22);

 cout << rec01.GetWidth() << " " << rec01.GetLength() << endl;
 cout << rec02.GetWidth() << " " << rec02.GetLength() << endl;

 rec01 = rec02;

 cout << rec01.GetWidth() << " " << rec01.GetLength() << endl;
 cout << rec02.GetWidth() << " " << rec02.GetLength() << endl;

 rec02.SetLength(33.44);
 rec02.SetWidth(11.22);

 cout << rec01.GetWidth() << " " << rec01.GetLength() << endl;

 return 0;
}

Next, let’s create a simple class for storing temperatures, called CTemperature. The CTemperature class will hold records on high and low temperature values. We will define a constructor that assigns initial values to the two private data members. The class will have two data access methods, one for retrieving the high temperature value and one for retrieving the low temperature value.

The class specification will go in the file CTemperature.h

#ifndef CTEMPERATURE_H
#define CTEMPERATURE_H

class CTemperature
{

 public:
 CTemperature(double highT, double lowT);
 void UpdateTemp(double temp);
 double GetHighTemp(void) const;
 double GetLowTemp(void) const;
 void PrintTemp(void);
 //private data members
 private:
 double _highTemp, _lowTemp;

};

#endif // CTEMPERATURE_H

Note the use of the const keyword after the methods for retrieving values. We use the const keyword here to tell the compiler that we do not want those data members modified in those methods.

For the implementation, each method in the class will be written outside of the class body using the class scope resolution operator. We will define these methods in a separate file called CTemperature.cpp.

#include "CTemperature.h"

//constructor
CTemperature::CTemperature(double high, double low)
{
 //this-> is optional
 this->_highTemp = high;
 this->_lowTemp = low;
}

//update high or low temp if parameter
//is above or below data members
void CTemperature::UpdateTemp(double temp)
{
 if(temp > this->_highTemp){
 this->_highTemp = temp;
 return;
 }
 if (temp < this->_lowTemp){
 this->_lowTemp = temp;
 return;
 }
}

//return data members
double CTemperature::GetHighTemp(void)const
{
 return this->_highTemp;
}

double CTemperature::GetLowTemp(void) const
{
 return this->_lowTemp;
}

//print values
void CTemperature::PrintTemp(void)
{
 std::cout << "Low: " << this->_lowTemp << " High: " << this->_highTemp << std::endl;
}

We can then try out using this class.

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

using namespace std;

int main()
{
 CTemperature tempObj(80.7, 55.5);

 tempObj.PrintTemp();

 tempObj.UpdateTemp(45.3);

 tempObj.PrintTemp();

 tempObj.UpdateTemp(86.2);

 tempObj.PrintTemp();

 return 0;

}

Objects can be passed as function parameters by value or by reference. How about we create a function to return the range of temperatures between the high temperature and the low temperature. This function will actually copy an object of type CTemperature and use that for calculating the temperature range. Since copying multiple objects can be considered wasteful, we will also create a version of this function that accepts a constant reference to the object, so that in effect only a pointer to the object is copied into the function.

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

using namespace std;

double GetRangeByVal(CTemperature objTemp)
{
 return objTemp.GetHighTemp() - objTemp.GetLowTemp();
}

double GetRangeByRef(const CTemperature& objTemp)
{
 return objTemp.GetHighTemp() - objTemp.GetLowTemp();
}

int main()
{
 CTemperature theTemp(89, 57.4);

 theTemp.PrintTemp();

 cout << "The range in temperatures is " << GetRangeByVal(theTemp) << endl;
 cout << "The range in temperatures is " << GetRangeByRef(theTemp) << endl;

 return 0;
}

That’s enough for today.

Geometric Series Summation in C++

An exponent is simply a quick way to show repeated multiplication. Exponential form shows that a number should be multiplied by itself a certain number of times. In other words, an exponent is a kind of algorithm.

#include <iostream>

using namespace std;

int main(void){

	int iBase, iExponent, iSum;

	cout << "Enter the value of the base: " << endl; 	
        cin >> iBase; 

	cout << "Enter the value of the exponent: " << endl; 	
        cin >> iExponent;

	iSum = 1;

	for(int i = 0; i < iExponent; i++){
		iSum *= iBase;
	}

	cout << iSum << endl;
	
	return 0;

}

Let’s take a look at a few short programs to come up with geometric series summation. With geometric series summation, we wish to add up a series of numbers that share a constant value and a common ratio. We will use the very simple geometric series summation that starts with a base value of 0, and iterates n number of times, with a constant value of x increased to the power of i, and added to the sum.

#include <iostream>

using namespace std;

int main(void){

	int iFirstTerm;
	int iCommonRatio = 2;
	int iNumberOfTerms = 10;
	int iSum = 0;

	int i, j;

	for(i = 0; i <= iNumberOfTerms; i++){
		iFirstTerm = 1;
		for(j = 0; j <= i; j++){
			iFirstTerm *= iCommonRatio;
			cout << iFirstTerm << " ";
		}
		iSum += iFirstTerm;
		cout << '[' << iSum << ']' << endl;
	}
	cout << "Sum: " << iSum << endl;

	return 0;

}

Let’s make this program interactive. We will make it so the user can supply the constant value and the number of terms in the series.

#include <iostream>

using namespace std;

int main(void){

	int iSum = 0;
	int i, j, iFirstTerm;
	int iNumTerms, iConstantRatio;

	cout << "Please enter the constant ratio: "; 	
        cin >> iConstantRatio;

	cout << "Please enter the number of terms: "; 	
        cin >> iNumTerms;

	for(i = 0; i <= iNumTerms; i++){
		iFirstTerm = 1;
		for(j = 0; j < i; j++){
			iFirstTerm *= iConstantRatio;
		}
		iSum += iFirstTerm;
		cout << iSum << " ";
	}
	cout << endl << "*** " << iSum << endl;

	return 0;

}

We can simplify our algorithm somewhat by applying Horer’s rule. Horner’s Rule is used to evaluate polynomials. Sigma notation when expanded leaves us with a polynomial. Applying this rule to our algorithm, we realize that the entire inner loop can be reduced to multiplying the sum figure by the number of terms plus one.

#include <iostream>

using namespace std;

int main(void){

	int iNumTerms, iConstantRatio, iIteration;
	
	int iSum = 0;

	cout << "Please enter the number of terms: "; 	cin >> iNumTerms;

	cout << "Please enter the constant ratio: "; 	cin >> iConstantRatio;

	for(iIteration = 0; iIteration <= iNumTerms; iIteration++){
		iSum = iSum * iConstantRatio + 1;
	}

	cout << "The sum is " << iSum << endl;

	return 0;

}

We can, of course, further improve upon the algorithm.

Review of Basic OOP Features in C++

We can derive a class from a base class with the simple syntax class ClassName : public BaseClass, where BaseClass is the name of the base class that the class indicated by ClassName is inheriting from. A class can inherit the public and protected members of a base class.

#include <cstdlib>
#include <iostream>

using namespace std;


class CAnimal{
public:
    void eat();
    void sleep();
};

void CAnimal::eat(){std::cout << "Eating. " << std::endl;}

void CAnimal::sleep(){std::cout << "Sleeping. " << std::endl;}

class CBird : public CAnimal{
public:
    void fly();
    void chirp();
};

void CBird::fly(){std::cout << "Flying." << std::endl;}
void CBird::chirp(){std::cout << "Chirping." << std::endl;}

int main(void) {

    CBird Polly;
    
    Polly.eat();
    Polly.fly();
    Polly.chirp();
    Polly.sleep();

    return 0;
}

We can specify the level of access a derived class has to a base class’s members using access specifiers. The members of a class can be declared to be public, private, or protected. Private members are not available to objects of other classes; public members are available to objects outside the class; protected members are available to objects of the same class or of derived classes.

CAnimal.h / CAnimal.cpp

#ifndef CANIMAL_H
#define    CANIMAL_H

class CAnimal {
public:
    CAnimal();
protected:
    void eat();
    void move();
};

#endif    /* CANIMAL_H */

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

CAnimal::CAnimal() {
}

void CAnimal::eat(){
    std::cout << "Eating." << std::endl;
}

void CAnimal::move(){
    std::cout << "Moving." << std::endl;
}

CKangaroo.h / CKangaroo.cpp

#ifndef CKANGAROO_H
#define    CKANGAROO_H
#include "CAnimal.h"

class CKangaroo : public CAnimal {
public:
    CKangaroo();
    void graze();
    void hop();
};

#endif    /* CKANGAROO_H */

#include "CKangaroo.h"

CKangaroo::CKangaroo() {
}

void CKangaroo::graze(){
    this->eat();
}

void CKangaroo::hop(){
    this->move();
}

main.cpp

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

using namespace std;

int main(void) {

    CKangaroo jack;
    jack.hop();
    jack.graze();

    return 0;
}

If a base class doesn’t have a defined constructor, its default constructor is called every time we create an object of a class derived from that class. If the base class does have an explicit constructor, we can choose the arguments we want to pass back to that constructor using initializers.

CAnimal.h / CAnimal.cpp

#ifndef CANIMAL_H
#define    CANIMAL_H
#include <iostream>
#include <string>

class CAnimal {
public:
    CAnimal();
    CAnimal(std::string sName);
protected:
    void eat();
    void move();
private:
    std::string _sName;
};

#endif    /* CANIMAL_H */

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

CAnimal::CAnimal() {
}

CAnimal::CAnimal(std::string sName){
    std::cout << "Initializing animal with name " << sName << "... ";
    
}

void CAnimal::eat(){
    std::cout << "Eating." << std::endl;
}

void CAnimal::move(){
    std::cout << "Moving." << std::endl;
}

CDog.h / CDog.cpp

#ifndef CDOG_H
#define    CDOG_H

#include "CAnimal.h"

class CDog : public CAnimal{
public:
    CDog(std::string sName);
    void BeFed();
    void Run();
};

#endif    /* CDOG_H */

#include "CDog.h"

CDog::CDog(std::string sName) : CAnimal(sName){
    std::cout << " Creating dog." << std::endl;
}

void CDog::BeFed(){
    std::cout << "Being fed.";
    this->eat();
}

void CDog::Run(){
    std::cout << "Running.";
    this->move();
}

main.cpp

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

using namespace std;


int main(void) {

    CDog Lucy("Lucy");
    Lucy.BeFed();
    Lucy.Run();
    
    return 0;
}

Note that a base class’s constructor is called before the derived class’s constructor, which makes sense, as the derived class may rely on base class members that should be already initialized.

Arrays and Searches in C++

Arrays are built-in data structures in most programming languages. An array is a fundamental data structure for lists. For many applications, we use search and sort utilities to find an item in an array-based list and to order the data.

A sequential search looks for an item in a list using a target value called the key. The search begins at a user-supplied index and traverses the remaining items in the array, comparing each item with the key until a match is found or the list is exhausted. If a key match has been found, a sequential search function will return the index of the matched element in the list. A negative value can also be returned to indicate that no match was found.

#include <iostream>


int seqSearch(int list[], int start, int bounds, int key);

int main(void){

    int iArray[] = {1706, 30, 45, 60, 90, 42, 1138, 47, 451, 6174, 73};
    int key, returnVal = 0;

    std::cout << "Please enter a value to search for: ";
    std::cin >> key;

    if((returnVal=seqSearch(iArray, 0, sizeof(iArray) / sizeof(int), key))<0){
        std::cout << "Value not found." << std:: endl;
    } else {
        std::cout << "Value found at index " << returnVal << std::endl;
    }

    return 0;

}

int seqSearch(int list[], int start, int bounds, int key){
    while(start < bounds){
        if(list[start]==key){
            return start;
        } else {
            start++;
        }        
    }
    //no match found
    return -1;
}

Ordering items in a list is an important task. To create an ordered list, let’s use a sorting algorithm called ExchangeSort that orders the items in ascending order. An exchange sort is a simple enough sorting algorithm; starting at the beginning of the array, we take each element and compare it with all the remaining elements in the array. If an element is smaller than the element being compared to then nothing happens, but if the element is larger than the element being compared to, then we switch the two elements.

#include <iostream>

//three user-defined functions

//swaps values via references
void Swap(int &x, int &y);
//performs sort
void ExchangeSort(int iArray[], int bounds);
//prints array
void PrintArray(int iArray[], int bounds);


int main(void){

    int iNums[] = {73, 6147, 2600, 8088, 47, 2001, 10538, 151, 88, 168, 250, 1999, 42};
    int iBounds = sizeof(iNums) / sizeof(int);
    PrintArray(iNums, iBounds);
    ExchangeSort(iNums, iBounds);
    PrintArray(iNums, iBounds);


    return 0;

}

void Swap(int &x, int &y){
    int temp = x;
    x = y;
    y = temp;
}

void ExchangeSort(int iArray[], int bounds){
    int outerIndex, innerIndex;
    int innerBounds = bounds--;
    for(outerIndex = 0; outerIndex < bounds; outerIndex++){
        for(innerIndex = outerIndex + 1; innerIndex < innerBounds; innerIndex++){
            if(iArray[innerIndex] < iArray[outerIndex]){
                Swap(iArray[innerIndex], iArray[outerIndex]);
            }
        }
    }
}

void PrintArray(int iArray[], int bounds){
    for(int i = 0; i < bounds; i++){
        printf("%d \t", iArray[i]);
    }
    printf("\n");
}

For our final program, we will search for certain C++ reserved words in a file. We will do so by creating a struct record for each reserved word; we will then create an array out of the keyword structures. The program will read its own source code as input.

#include 
#include 
#include 

using namespace std;

struct KeyWord{
	char szKeyWord[32];
	int iCount;
};

void SeqSearch(KeyWord *structArrayKeyword, int n, char *szPtr);
int GetWord(ifstream& fStreamIn, char *szPtr);

int main(void){

	KeyWord KeyWordTable[] = {
		{"int", 0}, {"char", 0}, {"double", 0}, {"struct", 0}, 
		{"include", 0},
		{"sizeof", 0}
	};

	const int KeyWordTableBounds = sizeof(KeyWordTable) / sizeof(KeyWord);

	char szWord[256];
	ifstream fStreamIn;

	fStreamIn.open("blog.cpp", ios::in);
	if(!fStreamIn){
		printf("Error opening file.\n");
		exit(EXIT_FAILURE);
	}

	while(GetWord(fStreamIn, szWord)){
		printf("%s ", szWord);
		SeqSearch(KeyWordTable, KeyWordTableBounds, szWord);
	}

	for(int i = 0; i < KeyWordTableBounds; i++){
		printf("%s %d times\n", KeyWordTable[i].szKeyWord, KeyWordTable[i].iCount);
	}

	return 0;

}


int GetWord(ifstream & fStreamIn, char *szPtr){

	char c;
	int i = 0;
	//skip all numbers, spaces, etc
	while(fStreamIn.get(c) && !isalpha(c)) {;}

	//return 0 if EOF reached
	if(fStreamIn.eof()){return 0;}

	//record first letter
	*(szPtr++) = c;

	//collect letters
	while(fStreamIn.get(c) && isalpha(c)){
		*(szPtr++) = c;
	}

	*(szPtr++) = '';

	//return success 
	return 1;
}



void SeqSearch(KeyWord *structArrayKeyword, int n, char *szPtr){
	
	for(int i = 0; i szKeyWord)==0){
			//increment counter for that struct
			(structArrayKeyword+i)->iCount++;
			return;
		}
	}
}

 

 

 

 

 

Class Inheritance in C++

Class inheritance is one of the pillars of object oriented programming. Class inheritance allows us to reuse our classes by deriving new classes from old one and customizing the new classes as needed. We’ll start with an an example class, called animal.

The animal class is defined using the class keyword, followed by the class name and then a pair of matching curly braces. Within the curly braces we will define the class’s behavior and state. Classes are typically divided into two sections, a public section and a private section. The public section is defined via the public keyword followed by a colon; likewise, the private section is defined with the private keyword followed by a colon.

Class definitions typically are placed in a header file with the .h extension. We ought to surround the class definition with an include guard, which keeps the header file from being included more than once in a program. Often, we can use the preprocessor directive #pragma once to act as an include guard; however, as of this moment #pragma once is not part of the official standard, so instead we will use #ifndef followed by the #define preprocessor directives.

#ifndef ANIMAL_H
#define	ANIMAL_H

class animal {
public:
    
private:
    
};

#endif	/* ANIMAL_H */

Note that the class definition ends with a semicolon after the closing brace; this is kinda unusual, compared to other languages like Java or C#.

The behavior for the animal class is implemented in a file with the .cpp extension.

 animal.h

#ifndef ANIMAL_H
#define	ANIMAL_H

class animal {
public:
    void eat();
    void sleep();
    void breathe();
private:
    
};

#endif	/* ANIMAL_H */

 animal.cpp

#include "animal.h"
#include 

void animal::eat(){ std::cout << "Eating!" << std::endl;}
void animal::sleep() { std::cout << "Sleeping!" << std::endl;}
void animal::breathe() { std::cout << "Breathing!" << std::endl;}

We can then use this class in our main code. Each instance of the animal class should be able to do three things – eat, sleep and breathe, functions that are common to all animals.

main.cpp

#include <cstdlib>
#include "animal.h"

using namespace std;

int main(int argc, char** argv) {

    animal aardvark;
    
    aardvark.eat();
    aardvark.breathe();
    aardvark.sleep();
    
    return 0;
}

The animal class methods are pretty basic. What if we want an animal that can fly or swim? We can customize the animal class by using it as a base class for other, more specific classes.These classes will be derived from the animal base class, which means they will still have the functionality of the original animal class, plus methods all their own. To have a derived class inherit from a base class, just include a colon followed by the keyword public and then the name of the class in the derived class’s definition.

bird.h

#ifndef BIRD_H
#define	BIRD_H

#include "animal.h"

class bird : public animal{
public:
    void fly();
    void sing();
private:

};

#endif	/* BIRD_H */

bird.cpp

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

void bird::fly(){std::cout << "Flying!" << std::endl;}
void bird::sing(){std::cout <<"Chirp!Chirp!" << std::endl;}

main.cpp

#include 
#include "bird.h"

using namespace std;

int main(void) {

    bird bluebird;
    
    bluebird.fly();
    bluebird.eat();
    bluebird.sing();
    bluebird.sleep();
    
    return 0;
}

Inheritance enables us to add functionality to an existing class by adding additional methods. Inheritance also allows us to add additional data members to an existing class. Finally, we can change how an existing class method works by overriding it in the derived class.

Inheritance is based on a “is-a” relationship; for example, a bird is an animal.

Members of a class can be declared private, public, or protected. Private members are not available outside of the class, public members are available outside the class, and protected members are available to classes that derive from the class.

Class methods and data members that we want to be private, but still available to classes that inherit from it, should be declared protected.

Let’s create a new base class, vehicle, that will have some actions common to all vehicles – it will start, stop, and move, and it will have a name. However, we don’t anyone to use just a generic ‘vehicle’, so in order to utilize the start(), stop() and move() methods, they will need to do so through a derived class, such as an airplane. In order to enforce this behavior, we will make the start(), stop() and move() methods protected.
vehicle.h

#ifndef VEHICLE_H
#define	VEHICLE_H
#include 

class vehicle {
public:
    std::string GetName();
protected:
    void Move();
    void Start();
    void Stop();
private:
    std::string _name;
};

#endif	/* VEHICLE_H */

vehicle.cpp

#include "vehicle.h"
#include 
#include 

std::string vehicle::GetName() {return this->_name; }
void vehicle::Move() {std::cout << "Moving!" << std::endl; }
void vehicle::Start() {std::cout << "Starting!" << std::endl;}
void vehicle::Stop() {std::cout << "Stopping!" << std::endl;}
   
void Stop();

Now let’s create a derived class called car. The car class will have its own private data member, _numberOfWheels, as well as its own public methods, such as driveTheCar(), startTheCar() and stopTheCar().
car.h

#ifndef CAR_H
#define	CAR_H

#include "vehicle.h"

class car : public vehicle {
public:
    int getNumberOfWheels();
    void driveTheCar();
    void startTheCar();
    void stopTheCar();
private:
    int _numberOfWheels;
    
};

#endif	/* CAR_H */

car.cpp

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

int car::getNumberOfWheels(){return this->_numberOfWheels;}

void car::driveTheCar(){
    std::cout << "Pressing the gas." << std::endl;
    Move();
}
void car::startTheCar(){
    std::cout << "Turning the car on." << std::endl;
    Start();
}

void car::stopTheCar(){
    std::cout << "Pressing the break." << std::endl;
    Stop();
}

main.cpp

#include "car.h"

int main(void) {

    car theCar;
    
    theCar.startTheCar();
    theCar.driveTheCar();
    theCar.stopTheCar();
    
    return 0;
}

Unfortunately, we do not actually have methods to set either the vehicle’s name or the number of wheels for the car. Let’s use the class constructor to do this.

If a base class does not have an explicitly defined constructor, its default constructor is called each time we create an object of a class derived from that class. However, if a base class has an explicit constructor, we need to add a list of initializers to the derived class’s constructor, that way we can pass arguments back to base class constructors.
car.h

#ifndef CAR_H
#define	CAR_H
#include <iostream>
#include "vehicle.h"

class car : public vehicle {
public:
    //constructor
    car(std::string carName, int numWheels);
    int getNumberOfWheels();
    void driveTheCar();
    void startTheCar();
    void stopTheCar();
private:
    int _numberOfWheels;
    
};

#endif	/* CAR_H */

car.cpp

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

car::car(std::string carName, int numWheels) : vehicle(carName){
    this->_numberOfWheels = numWheels;
}

int car::getNumberOfWheels(){return this->_numberOfWheels;}

void car::driveTheCar(){
    std::cout << "Pressing the gas." << std::endl;
    car:Move();
}
void car::startTheCar(){
    std::cout << "Turning the car on." << std::endl;
    Start();
}

void car::stopTheCar(){
    std::cout << "Pressing the break." << std::endl;
    Stop();
}

main.cpp

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

using namespace std;

int main(void) {

    car theCar("Toyota", 4);
    
    cout << "The car is a " << theCar.GetName() << " and has " << theCar.getNumberOfWheels() << " wheels." << endl;
    
    theCar.startTheCar();
    theCar.driveTheCar();
    theCar.stopTheCar();
    
    return 0;
}


If you’re interested, please check out my book http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M