user2761431
user2761431

Reputation: 975

Inheritance in C

I am playing with implementing inheritance in C. I wrote the following two variations of it. Method 1 crashes while running the program, but Method 2 works fine. What am I doing wrong in Method 1?

Method 1:

#include<stdio.h>
#include<stdlib.h>

typedef struct base_class
{
    int a;
}Base;

typedef struct derived_class
{
    int b;
    Base *base_ptr;
}Derived;

int main(void){
    Derived *der_ptr;
    der_ptr = (Derived *)malloc(sizeof(Derived));
    der_ptr->b = 5;
    der_ptr->base_ptr->a=10;

    printf("%d %d",der_ptr->b,der_ptr->base_ptr->a);
}

Method 2:

#include<stdio.h>
#include<stdlib.h>

typedef struct base_class
{
    int a;
}Base;

typedef struct derived_class
{
    int b;
    Base base_ptr;
}Derived;

int main(void){
    Derived *der_ptr;
    der_ptr = (Derived *)malloc(sizeof(Derived));
    der_ptr->b = 5;
    der_ptr->base_ptr.a=10;

    printf("%d %d",der_ptr->b,der_ptr->base_ptr.a);
}

Upvotes: 4

Views: 222

Answers (3)

Andrew Hacking
Andrew Hacking

Reputation: 6366

As others have already indicated you are not allocating storage for Base so Method 1 will cause random access to some location in memory.

If you are interested in implementing OO like interfaces and higher level programming in C then I recommend taking a good look at libCello, you will be surprised at the expressiveness afforded.

Upvotes: 1

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53016

Nothing wrong in method 2, but it depends on what are you trying to achieve.

In method 1 however, you are never allocating space for the pointer Base *base_ptr and then you are dereferencing it, that is why your program is crashing.

This, and notice that i've removed the cast because while it's needed in c++, it's not needed in c

der_ptr = malloc(sizeof(Derived));

is allocating space for one int and one pointer, so sizeof(Derived) = sizeof(int) + sizeof(void *), if you want to access the a member of base_ptr you need to allocate space for it to, after allocating for the der_ptr and checking that allocation was successful, you then allocate for it's base_ptr member, like this

der_ptr->base_ptr = malloc(sizeof(Base));

and then you can access base_ptr's a member.

Also, please note that unlike the new operator in c++ which does some of it's exception handling thing when it fails, in c you should check that malloc returned a valid pointer, on failure it returns NULL.

So, your method 1 should work like this

#include<stdio.h>
#include<stdlib.h>

typedef struct base_class
{
    int a;
} Base;

/*
  typedef struct derived_class
  {
      int b;
      Base *base_ptr;
  } Derived;
*/

/* the order matters, this way you can cast Derived to Base */
typedef struct derived_class
{
    Base *base_ptr;
    int b;
} Derived;

int main(void) {
    Derived *der_ptr;

    der_ptr = malloc(sizeof(Derived));
    if (der_ptr == NULL)
        return 1;

    der_ptr->b        = 5;
    der_ptr->base_ptr = malloc(sizeof(Base));
    if (der_ptr->base_ptr == NULL)
    {
        free(der_ptr);
        return 2;
    }
    der_ptr->base_ptr->a = 10;

    printf("%d %d", der_ptr->b, der_ptr->base_ptr->a);

    free(der_ptr->base_ptr);
    free(der_ptr);
}

and notice that you can also cast Derived * to Base * now that the members are in this order.

Upvotes: 4

wallyk
wallyk

Reputation: 57784

Method 1 crashes because of this line of code:

der_ptr->base_ptr->a=10;

Ask yourself: What is the value of der_ptr->base_ptr?

Upvotes: 5

Related Questions