const

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.

Arrays in C++

An array is a collection of scalar values of the same type, placed in consecutive memory locations and accessed via an identifier that devolves to a pointer to the base address combined with an offset value.

An array is a collection of data items of the same type, grouped under a single name and accessed by a number that indicates its location in the collection.

An array is a group of values accessed by an index number, which is placed in square brackets after the array’s name.  The index number counts from 0, not 1, because it indicates an offset from the base (or first) memory address of the array. Thus, item 1 is item 0, item 2 is item 1, and so on.

To declare a simple array, we declare the data type, followed by the array’s indentifier. It’s the same as a regular variable, with one addition: after the variable’s identifier, we place square brackets and a number. The number tells the compiler how many discrete items we want the array to be able to hold.

#include <iostream>


int main(void){

    //array of 10 ints
    int iaNums[10];

    //array of 10 doubles
    double daNums[10];

    //array of 20 chars
    double caChars[20];

    return 0;

}

Remember, an array is a homogeneous data structure, where all components are of the same data type.

Each item in an array is known as an element. An element is accessed by its position in the array. We specify the index value to access the element; note that array elements are counted from 0, not 1.

#include <iostream>

int main(void){

    int iaNums[5];

    iaNums[0] = 1138;
    iaNums[1] = 4004;
    iaNums[2] = 47;
    iaNums[3] = 1701;
    iaNums[4] = 1999;

    std::cout << "The first element is " << iaNums[0];
    std::cout << std::endl;

    std::cout << "The last element is " << iaNums[4];
    std::cout << std::endl;


    return 0;
}

As we have seen above, to access an array element, we write the array name, followed by an expression enclosed in square brackets. Although in the previous example we gave literal values, we can in fact place a variable or even a complex expression within the brackets, as long as the expression resolves to an integer. We can take advantage of this fact by using loops and variables to cycle through an array quickly.

#include <iostream>

using namespace std;

int main(void){

    int iaValues[5];

    int iIndex = 0;

    while(iIndex < 5){
        iaValues[iIndex] = iIndex * 3;
        iIndex++;
    }

    cout << "Third value: " << iaValues[2] << endl;
    cout << "First value: " << iaValues[0] << endl;

    

    return 0;
}

Note that C++ does not perform bounds checking, either at compile time or run time. Be careful!

It is possible to initialize an array at the time of its declaration. We specify a list of initial values for the array’s elements, separate them with commas, and enclose the list within curly braces.

#include <iostream>

using namespace std;

int main(void)
{
    double dArray[3] = {169.254, 802.11, 255.128};

    int i;

    for(i = 0; i < 3; i++){
        cout << dArray[i] << endl;
    }

    return 0;
}
        

By default, in C and C++ variables are passed by value. Arrays, however, are passed by reference. Note that when passing in an array, we must specify its upper bound either in a global variable or in a second argument.

#include <iostream>

#define LENGTH 5

using namespace std;

void printCharArray(char caArray[], int bounds);
void getGrades(char caGrades[]);

int main(void){

    char caGrades[7] = {'c', 'a', 'a', 'b', 'd', 'c', 'a'};
    char caGradesTwo[LENGTH];


    printCharArray(caGrades, 7);

    getGrades(caGradesTwo);

    printCharArray(caGradesTwo, LENGTH);


    return 0;
}


void printCharArray(char caArray[], int bounds){
    for(int i = 0; i < bounds; i++){
        cout << caArray[i] << endl;
    }
}

void getGrades(char caGrades[]){
    int i = 0;
    while(i < LENGTH){
        cout << "Enter the grade: ";
        cin >> caGrades[i];
        i++;
    }
}

In the even that we do not wish the called function to modify the contents of the array, we can use the reserved word const. We place the const reserved word before the parameter in the parameter list of the function.