Inheritance in C
I am playing with the implementation of inheritance in C. I wrote the following two options. Method 1 fails during program startup, 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);
}
Method 1 fails because of this line of code:
der_ptr->base_ptr->a=10;
Ask yourself: what is the meaning der_ptr->base_ptr
?
There is nothing wrong with Method 2, but it depends on what you are trying to achieve.
However, in method 1, you never allocate space for the pointer Base *base_ptr
and then you play it out, which is why your program crashes.
This and notice that I removed the cast because when needed in C ++ it is not needed in c
der_ptr = malloc(sizeof(Derived));
allocates space for one int
and one pointer, so sizeof(Derived) = sizeof(int) + sizeof(void *)
if you want to access an element a
base_ptr
, you need to allocate space for it, after allocating for der_ptr
and checking that the allocation was successful, you then allocate an element for it base_ptr
like this
der_ptr->base_ptr = malloc(sizeof(Base));
and then you can access the item base_ptr
a
.
Also, note that unlike the operator new
in C ++, which performs some operations with exceptional handling when not present, in c you have to check that you malloc
returned a valid pointer, it returns on error 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 note that you can now cast Derived *
in Base *
when members are in that order.
As others have already pointed out, you are not allocating memory for Base, so method 1 will result in random access to some location in memory.
If you are interested in implementing OO and higher-level programming interfaces in C, I recommend taking a close look at libCello , you will be surprised at the expressiveness.