Lab #13. Examining object oriented constructs

Lab #13.1. Destructor

In C++, class objects can be manipulated in two ways (lab13.1.cpp):

·         directly” (variable of type <class>; elements (fields and methods) accessed via dot notation (.);

·         dynamically (variable of type <class>*, i.e., pointer to <class>; elements (fields and methods) accessed via arrow (“points-to”) notation (->).

#include <iostream>

using namespace std;

 

class person

{

private:

    char *name;

    int age;

public:

    person (const char *n, int a) { init (n,a); };

    person () {};

    ~person ();

    void init (const char*, int);

    void print () { cout << name << " " << age << endl; }

};

 

int main ()

{

    person p;

    p.init ("Liz", 19);

    p.print ();

    person *pp = new person ("Peter", 20);

    pp->print ();

    delete pp;

    return 0;

};

 

person::~person ()

{

    cout << "Deleting: " << name << endl;

    delete[] name;

};

 

void person::init (const char *n, int a)

{

    name = new char[strlen(n)+1];

    strcpy (name, n);

    age = a;

}

Destructor is a method of class, which is automatically called right before the deletion of an object. There is exactly one and only one constructor per class.

Observe the call of destructors in the example above – the first destructor to execute is that of Peter, then of Liz.

That’s because for dynamic objects destructors are called explicitly with operator delete, but for “direct” (automatic) object – automatically at the end of the block the object is declared.

 

Lab #13.2. Constructors

(lab13.2.cpp)

#include <iostream>

using namespace std;

 

class timesimple

{

    int hours, minutes;

public:

    timesimple (int h, int m)

    {

        hours = h;

        minutes = m;

        cout << "C1 " << hours << ":" << minutes << endl;

    };

    timesimple (const timesimple &t)

    {

        hours = t.hours + 1;

        minutes = t.minutes + 1;

        cout << "C2 " << hours << ":" << minutes << endl;

    };

    timesimple (int h): hours(h), minutes(0)

    {

        cout << "C3 " << hours << ":" << minutes << endl;

    };

    timesimple ()

    {

        cout << "C4" << endl;

    };

    void print () const;

};

 

int main ()

{

    timesimple t (8, 20);

    t.print ();

    timesimple u = t;

    u.print ();

    timesimple v;

    v = t;

    v.print ();

    timesimple w = 23;

    w.print ();

    return 0;

};

 

void timesimple::print () const

{

    cout << hours << ":" << minutes << endl;

}

Constructor is a method, which is automatically called right before the creation of an object. Unlike destructors, a class can contain several constructors (but at least one). Specific constructors are those with exactly one parameter, because they can be called implicitly by object’s initialization (during declaration) or passing an object by value through parameter.

Observe the call of constructors here – especially of those with one parameter (C2, C3).

 

Lab #13.3. Examining creation of a dynamic array

(lab13.3.cpp)

#include <iostream>

using namespace std;

 

class dynamicarray

{

    int Size;

    int *Array;

public:   

    dynamicarray (int s=0)

    {

        Size = s;

        if (Size > 0) Array = new int[Size];

    };

    ~dynamicarray ()

    {

        if (Size > 0)

        {

            cout << Size << " elements deleted." << endl;   

            delete[] Array;

        }

    };

    void append (int value)

    {

        int *tmparray = new int[Size+1];

        for (int i=0; i<Size; i++) tmparray[i] = Array[i];

        tmparray[Size] = value;

        Size++;

        delete[] Array;

        Array = tmparray;

    };

    void print ()

    {

        for (int i=0; i<Size; i++) cout << Array[i] << endl;

    };

    int& operator[] (int i) { return Array[i]; };

};

 

int main ()

{

    dynamicarray arri(2);

    arri[0] = 11;

    arri[1] = 22;

    arri.append (33);

    arri.print ();

    return 0;

}

A true sense for a destructor actually appears almost only if an object contains dynamic structures (or operates over some other resources), and the destructor is the right place to specify which dynamic structures should be deleted by the deletion of the object.

The current example contains a simplified implementation of a dynamic array of int and demonstrates the meaningful usage of destructor. In addition, the example contains overloading of operator [] for convenient access of elements of dynamicarray objects.