C++ part6

26. Pointers to classes (objects)

First of all, one of the biggest achievements of using pointers is that you can directly access memory locations, which is a very good feature to use in low-level programming. I’m working in the embedded field and I cannot conceive writing my code without using pointers. When programming an embedded system you’re somehow “God” on that system, it is strongly required to have the permission to fully access any memory location.
Besides this pointers are very handy. A program written with pointers will be smaller and more efficient than the pointer-less variant.

If you need to access an element of your class (method or member) you have to choices: either you define an instance of that class, or you define a pointer to that class, to access its elements. If you define an instance this will occupy as much memory as the number of its members, but if you define a pointer this will occupy just a pointer-size memory. Just see the example below:


class Example
{
int a, b;
}

int main()
{
Example ex; // this will occupy 2 int’s, probably 8 bytes
Example *pex; //this will occupy as much as an ordinary pointer, usually 4 bytes (generally pointers
// occupy same size as the machine- on a 32-bit CPU, a pointer will nedd 32 bits)
return 0;
}

Another big advantage of using pointers in C++ is when you need to pass arguments of a class type. Suppose you have such function:


void function (Example a, Example b)
{
..
}

Here the parameters are passed by value, so a copy of two Example objects needs to be done by the copy constructor. This involves two overheads: a longer execution time (copy constructor needs to be called twice to make this copy) and a memory overhead (two local Example objects will be created by copy and used just during the execution time of function).

#include
using namespace std;

class Heater
{
// Declare public functions for class heater
public:
// constructor to initialize temperature
Heater( int itsTemperature);
// destructor, takes no action
~Heater();
// accessor function to retrieve temperature
int getTemperature() const;
// declare private data members
private:
int temperature;
};
// definition of constructor
Heater::Heater(int itsTemperature)
{
temperature = itsTemperature;
}
// definition of destructor
Heater::~Heater()
{
// no action taken here
}
// Definition of an accesor function which returns a value of a private Heater class member temperature
int Heater::getTemperature() const
{
return temperature;
}

int main()
{
// define a Heater class pointer object and initialize temperature to 8 by use of constructor
Heater * modelXYZ = new Heater(8);
// Access an accessor function getTemperature() to retrieve temperature via an object modelXVZ
cout << “Temperature of heater modelXYZ is :” << modelXYZ->getTemperature() << endl;
// Free an allocated memory back to a free store
delete modelXYZ;
return 0;
}

The example above shows the use of class pointers. Those can be declared in two ways: statically and dynamically. In this example a Heater pointer is declared dynamically after it is out of use the pointer is “deleted”, meaning that it doesn’t point to a Heater object anymore.

You can see that -> notation, instead of .(dot), is used to access an element of the class.

A very good use of the pointers to classes is when making use of virtual functions via polymorphism. A pointer to a base class can refer to a method from the base class but also to one in the derived class. This thing is not valid for objects as well, you cannot a base object and refer to a method from a derived class, simply because base classes are not aware of the inheritance tree below them.

27. Diamond inheritance – a paradigm encountered in object-oriented languages, which in C++ is known under the name of virtual inheritance

For example Java language handles this in a different way than C++. This problem basically arises when two classes B and C inherit from a class A, and a fourth class D inherits both B and C classes. The picture below is clearer

The main problem here is that in D class there are two different instances of class A. In order to explain this more in detail let’s go through the next simple example:

class A
{
public:
void functionA();
..
}

class B: public A
{
public:
void functionB();

}

class C: public A
{
public:
void functionC();

}

class D: public B, public C
{
public:
void functionD();
..
}

int main()
{
D d;
d.functionA(); // in normal conditions this would be OK
// but given the situation that basically two copies of A reside in D, this call is ambiguous
..
}

The way in which C++ compilers generate the executable (and implicitly those problems :)) is the following: when an inheritance tree exists, the child instance is placed after the parent instance, particularly in this case the memory layout will look like below.

A instance B instance A instance C instance D instance

The solution at this problem is very similar to the way polymorphism (we’ll see later on) handles virtual functions, virtual inheritance. In order to get only one instance of a base class which is derived in such manner as the one exposed, the inheritance has to be made virtual.

class A
{
public:
void functionA();
..
}

class B: virtual public A
{
public:
void functionB();

}

class C: virtual public A
{
public:
void functionC();

}

class D: public B, public C
{
public:
void functionD();
..
}

int main()
{
D d;
d.functionA(); // in normal conditions this would be OK
// but given the situation that basically two copies of A reside in D, this call is ambiguous
..
}

As I said, exactly as it is the case for virtual functions, every instance of a class which virtually inherits from another one receives an additional pointer, called vptr . Those are, indeed, slightly bigger than their counterparts which do not inherit virtually and, as a consequence, class D will have also those two pointers. There will be one single copy of A instance in class D but with two vptr pointers, each one indicating the path through which D inherits from A class.
Basically this is the idea with virtual inheritance, one of the preferred subjects at C++ interviews and also one of the “advanced” stuff in C++. Of course this discussion may go further with the way Java handles this, via interfaces, but it is not the subject of this post and also of this topic. You can find many more things about virtual inheritance and related stuff, like “sister class delegation” here.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: