-2

I am new to inheritance and overall opp, I am still learning. But, if anyone can help me get started with my UML Design into code implementation from the image below. I will be thankful for the help. Thanks for the help.

Also, I think my UML design is missing something. Can you check if my UML design is missing anything?

2 Answers2

3

C does not support inheritance or OOP, so you need to implement it yourself. There are a couple of useful techniques that are helpful

struct extension

C guarantees that the first field in a struct will be at offset 0, so you can freely cast between a pointer to a struct and a pointer to the struct's first field. This allows easy extension of a struct for deriving:

struct BaseClass {
       ...whatever
};

struct DerivedClass {
    struct BaseClass base;
    ... derived class additions
};

Here you can take a (pointer to) an instance of DerivedClass and cast to BaseClass * and it will work. You can also cast a BaseClass * back to a DerivedClass * if the pointer is known to point at an actual DervicedClass

metaclass objects

You can implement OO dispatch using metaclass structs containing function pointers

struct BaseClass;
struct BaseMetaclass {
    void (*method1)(struct BaseClass *);
    int (*method2)(struct BaseClass *, int);
};
struct BaseClass {
    struct BaseMetaclass *isa;
    ....
};

Now you can create a single instance of BaseMetaclass used by all instances of BaseClass and call the method via the isa pointer.

  base_obj->isa->method1(base_obj);

Derived classes can use BaseMetaclass directly if they don't need to add any new methods, or can define a DerivedMetaclass using struct extension with additional fields. You can also put any other class-oriented data you like in the metadata objects (a string constant with the name of the class is useful).

Chris Dodd
  • 101,438
  • 11
  • 111
  • 197
  • 3
    @CareyGregory Yes, using an existing OO language is better than reinventing the wheel, but if you must use C for some reason, then it can be done. – Chris Dodd Oct 03 '19 at 01:29
  • @ChrisDodd can you show me based of my uml design please? thanks – user11703752 Oct 03 '19 at 01:36
  • @user11703752 the diagram is hardly readable it would be difficult to produce an accurate implementation – dvhh Oct 03 '19 at 02:12
  • @ChrisDodd _Maybe_ it can be done, but I've never seen a successful implementation of it, and if I ever do I'm confident it will be a contrived mess that costs more to implement and maintain than it's worth. Wrong tool for the job. Simple as that. C++ can be written and maintained by anyone who knows C and it actually supports the things OP wants to do. – Carey Gregory Oct 03 '19 at 04:02
0

In pure C, I've implemented it like this:

// in interface.h file
typedef struct st_interface interface_t;
typedef int32_t (*interface_fn)(interface_t *i);

struct st_interface {
     interface_fn fn1;
     interface_fn fn2;
     void* impl;
};

// in interface_impl.h
interface_t* interface_impl_new();

// in interface_impl.c file
typedef struct {
    // impl data
} interface_impl_t;

static int32_t interface_impl_fn1(interface_t* i) {
    interface_impl_t* impl = i->impl;
}

static int32_t interface_impl_fn2(interface_t* i) {
    interface_impl_t* impl = i->impl;
}

interface_t* interface_impl_new() {
     uint8_t* mem = malloc(sizeof(interface_t) + sizeof(interface_impl_t));

     if (mem == NULL) {
          return NULL;
     }

     interface_t* i = (interface_t*) mem;
     interface_impl_t* impl = (interface_impl_t*) (mem + sizeof(interface_t));

     *i = (interface_t) {
         .fn1 = interface_impl_fn1,
         .fn2 = interface_impl_fn2,
         .impl = impl,
     };

     *impl = (interface_impl_t) {
         // init impl
     };

     return i;
}
sturcotte06
  • 1,838
  • 1
  • 9
  • 18