private

C++ Classes Review

Classes differ from structures in that they allow for data hiding, abstraction and encapsulation, inheritance,  and polymorphism. With a class definition, the class name is a type of name. A class is an abstract data type; a class specifies how objects of its type behave, are created and deleted, and are accessed.

The keywords private, protected, and public are used to specify three levels of access protection for data hiding and utility methods. private means that the member can only be accessed by the member functions and friends of the class. The private member is not directly accessible to the outside world. public means that member can be accessed by any function in the external environment. Public methods are interfaces to the outside world so that any other function can interact with it. protected means that the member can only be accessed by the class and member functions and classes derived from this class.

#include <iostream>

class CClock
{
    public:

        //constructors
        CClock();
        CClock(int h, int m, int s);

        //getters - setters
        void setHour(int h);
        void setMinute(int m);
        void setSecond(int s);

        int getHour() const;
        int getMinute() const;
        int getSecond() const;

        void printTime();

    private:

        int _hour;
        int _min;
        int _sec;
};

Member functions of a class are typically defined outside the class header file. The scope resolution operator, ::, is used to assign the function to a class.

The first member functions we can look at are the constructors. Constructors are special methods that are called automatically when an object of a class type is created. The constructor or constructors job is to initialize the object’s state – it’s member variables. If no constructor is specified then the compiler provides one by default.

Since C++ does not have zero initialization of member variables such as ints, it is a good idea to modify the default constructor so that it sets a default value for each member.

//default constructor
CClock::CClock()
{
    _min = 0;
    _hour = 0;
    _sec = 0;
}

//initialize the member variables to specific values
CClock::CClock(int h, int m, int s){
    _min = m;
    _sec = s;
    _hour = h;
}

Getters and setters are used to assign values to data members. Getters are usually declared to be const so as to ensure that the values aren’t accidentally modified during retrieval. Setters often do value checking to ensure that the new data is in the proper range.

//setters
void CClock::setHour(int h){
    //only set hour if it falls in the range 0 - 23
    if(0 <= h && h < 24){
        _hour = h;
    }
}

void CClock::setMinute(int m){
    if(0 <= m && m < 60){
        _min = m;
    }
}

void CClock::setSecond(int s){
    if(0 <= s && s < 60){
        _sec = s;
    }
}

//getters
int CClock::getHour() const {
    return _hour;
}

int CClock::getMinute() const {
    return _min;
}

int CClock::getSecond() const {
    return _sec;
}

Finally, we will set up a method to print the data in a formatted manner.

void CClock::printTime(){
    if(_hour < 10){
        cout << "0";
    }
    cout << _hour << ":";

    if(_min < 10){
        cout << "0";
    }
    cout << _min << ":";

    if(_sec < 10){
        cout << "0";
    }
    cout << _sec;
}

There are two ways to access a member of a class. We typically access a data or function member of the class object using ., the dot operator.When a pointer to an object of a class is used, we use the -> operator to access data or function members of the class.

#include "CClock.h"

using namespace std;

int main()
{
    CClock clockOne;
    CClock clockTwo(22, 15, 00);

    cout << "Clock One after default initialization: ";
    clockOne.printTime();
    cout << endl;

    cout << "Clock Two after being initialized to a specific time: ";
    clockTwo.printTime();
    cout << endl;

    clockOne.setHour(3);
    clockOne.setMinute(33);
    clockOne.setSecond(15);

    cout << endl;
    clockOne.printTime();

    return 0;
}

Access Specifiers in C++

The access specifiers private, protected, and public are used to set the access of a class’s members. We can make members private, visible only to code belonging to the same class, protected, visible to code only in the same class or classes derived from it, or else public, visible to all. By default, all members of a class are private.

#include <iostream>

using namespace std;


class CExmp{

    private:
        int _number;
    public:
        void incrementNumber();
        int getNumber();
        CExmp(int i);

};

CExmp::CExmp(int i){
    this->_number = i;
}

void CExmp::incrementNumber(){
    this->_number++;
}

int CExmp::getNumber(){
    return this->_number;
}


int main(void){


    CExmp objEmpOne = CExmp(47);
    
    objEmpOne.incrementNumber();

    cout << objEmpOne.getNumber() << endl;

    objEmpOne.incrementNumber();

    cout << objEmpOne.getNumber() << endl;

    return 0;

}

Note that as members are private by default, the private declaration isn’t, strictly speaking, necessary.

An important aspect of object oriented programming is data hiding. Data stored in an object should only be accessed via specific data access methods. In that way, we can control access to the data, ensuring that no illegal values are stored, and making sure the functionality of the object is predictable. We usually implement data access methods in pairs, as get and set methods, where the set method stores the data, and the get method retrieves the data.

#include <iostream>
#include <string>

using namespace std;

class CBikes{
    private:
        int _inStock;
        string _brand;
    public:
        void setInStock(int n);
        int getInStock();

        bool sellBikes(int n);
        
        string getBrand();
        
        CBikes(string s);
        

};

CBikes::CBikes(string s){
    this->_brand = s;
}

void CBikes::setInStock(int n){
    this->_inStock = n;
}

int CBikes::getInStock(){
    return this->_inStock;
}

bool CBikes::sellBikes(int n){
    if(this->_inStock - n >= 0){
        this->_inStock -= n;
        return true;
    } else {
        return false;
    }
}

string CBikes::getBrand(){
    return this->_brand;
}

int main(void){

    CBikes objSchwinn = CBikes("Schwinn");
    objSchwinn.setInStock(10);

    CBikes objGiant = CBikes("Giant");
    objGiant.setInStock(15);

    cout << "We have " << objSchwinn.getInStock() << " " << objSchwinn.getBrand() << "(s)" << endl;
    cout << "We have " << objGiant.getInStock() << " " << objGiant.getBrand() << " (s)" << endl;

    cout << "Selling 5 of the " << objSchwinn.getBrand() << "(s)" << endl;
    cout << "We now have " << objSchwinn.getInStock() << " of the " << objSchwinn.getBrand() << "(s)" << endl;

    cout << "Can we fill an order for 20 of the " << objGiant.getBrand() << "(s) ?" << endl;
    if(objGiant.sellBikes(20)){
        cout << "Yes! Sold. We now have " << objGiant.getInStock() << " left." << endl;
    } else {
        cout << "Nope. Not enough bikes." << endl;
    }

    return 0;

}

We use constructors to initialize data in an object as that object is being created. A constructor is a special method that is invoked automatically when the object is created. A constructor has the same name as the class itself, and not return value. When we declare objects, we can pass values to the constructor to initialize the state of the object.

#include <iostream>
#include <string>

using namespace std;

class CPet{
    private:
        string _name;
        string _type;
        int _age;
    public:
        string getName();
        void setName(string s);

        string getType();

        int getAge();
        void setAge(int n);

        CPet(string name, string type, int age);
};


string CPet::getName(){
    return this->_name;
}

void CPet::setName(string s){
    this->_name = s;
}

string CPet::getType(){
    return this->_type;
}

int CPet::getAge(){
    return this->_age;
}

void CPet::setAge(int n){
    this->_age = n;
}

CPet::CPet(string name, string type, int age){
    this->_name = name;
    this->_type = type;
    this->_age = age;
}


int main(void){

    CPet objDog = CPet("Fido", "dog", 5);
    CPet objBird = CPet("Polly", "bird", 3);

    cout << objDog.getName() << " is a " << objDog.getType() << " that is " << objDog.getAge() << " years old." << endl;
    cout << objBird.getName() << " is a " << objBird.getType() << endl;

    return 0;

}

If a constructor for the class is not provided, the compiler will provide one for us; this constructor is known as the default constructor.