Page 1 of 1

Behind the scenes - How C++ Classes Work : Part II Rate Topic: ***** 1 Votes

#1 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Posted 27 March 2011 - 09:13 AM

*
POPULAR

Behind the scenes - How C++ Classes Work : Part II

Introduction

In our previous tutorial, we looked at a simple C++ class, and the implementation of a constructor and member function by using pure C as a means of highlighting the compiler code that is generated 'behind the scenes'. This tutorial moves us forward and looks at how the C++ compiler generated code to handle inheritance. So without further ado, let's dive straight in!

Class Inheritance

Using the foo class from the previous tutorial as a base class, we are going to introduce a new class called fooed that inherits from foo. Here are the two classes without any methods.

class foo {
    public:
        int    m_counter;
        float  m_value;
        char * m_buffer;
};

class fooed : public foo {
    public:
        double m_double;
};



I have chosen to specify one extra data member in the derived fooed class for simplification. The equivalent C code as structures would be:

typedef struct {
        int    m_counter;
        float  m_value;
        char * m_buffer;
} foo;

typedef struct {
        foo m_foopart;
        double m_double;
} fooed;



As in the previous tutorial, both the class fooed and the structure fooed have exactly the same size of twenty bytes (a double field being eight bytes in length).

Creation and Deletion of Dynamically Inherited Objects

Let's now take a look at the C++ code for creating and deleting a fooed object. The small program below will do nicely.

#include <Windows.h>

class foo {
    public:
        int    m_counter;
        float  m_value;
        char * m_buffer;
	public:
		foo(int counter, float value, int length); 
		~foo();
};

foo::foo(int counter, float value, int length) 
        : m_counter(counter), m_value(value), m_buffer(new char[length]) { 
};

foo::~foo() {
	delete m_buffer;
}

class fooed : public foo {
    public:
        double m_double;
	public:
		fooed(int counter, float value, int length, double big_value);
		~fooed();
};

fooed::fooed(int counter, float value, int length, double big_value) : foo(counter, value, length), m_double(big_value) {
}

fooed::~fooed() {
}

int main(int argc, char **argv) {
	fooed * a = new fooed(10, 3.1f, 256, 20.0);
	delete a;
}



What happens behind the scenes in this example is


1. A call is made to the new operator to allocate the twenty bytes of member data
2. A call is made to the fooed constructor which in turn calls the foo constructor
3. A call is made to the fooed destructor which in turn calls the foo destructor
4. A call is made to the delete operator within the foo destructor for the m_buffer data member
5. A call is made to the delete operator within main to delete the fooed object


The equivalent code in pure C would therefore be:


#include <Windows.h>

typedef struct {
        int    m_counter;
        float  m_value;
        char * m_buffer;
} foo;

void foo_constructor(foo * this, int counter, float value, int length) {
	this->m_counter = counter;
	this->m_value = value;
	this->m_buffer = (char *)malloc(length);

}

void foo_destructor(foo * this) {
	free(this->m_buffer);
}

typedef struct {
        foo m_foopart;
        double m_double;
} fooed;

void fooed_constructor(fooed * this, int counter, float value, int length, double big_value) {
	foo_constructor((foo *)this, counter, value, length);
        m_double = big_value;
}

void fooed_destructor(fooed * this) {
	foo_destructor((foo *)this);
}

int main(int argc, char **argv) {
	fooed * a = (fooed *)malloc(sizeof(fooed));
	fooed_constructor(a, 10, 3.1f, 256, 20.0);
	fooed_destructor(a);
	free(a);
}



Tutorial Conclusion

In this tutorial, we can see that the C++ compiler generates even more code behind the scenes than we saw in the previous tutorial.

The next tutorial concerns itself with how C++ implements pure virtual functions, and the equivalent C code to help demystify that aspect of implementation. This tutorial may be found here.

This post has been edited by Martyn.Rae: 27 March 2011 - 09:17 AM


Is This A Good Question/Topic? 9
  • +

Page 1 of 1