Reputation: 975
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?
#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);
}
#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
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
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
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