Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism in C

Tags:

c

polymorphism

I'm designing a program in C that manipulates geometric figures and it would be very convenient if every type of figure could be manipulated by the same primitives.

How can I do this in C?

like image 987
Pedro Borges Avatar asked Dec 16 '10 01:12

Pedro Borges


People also ask

What is polymorphism and example?

The word “polymorphism” means having many forms. In simple words, we can define polymorphism as the ability of a message to be displayed in more than one form. A real-life example of polymorphism is a person who at the same time can have different characteristics.

Does C allow polymorphism?

Master C and Embedded C Programming- Learn as you goPolymorphism is a key feature of object oriented programming that means having multiple forms. This is divided into compile time polymorphism and runtime polymorphism in C++. An example of compile time polymorphism is function overloading or operator overloading.

What is polymorphism and types?

Polymorphism is the ability to process objects differently on the basis of their class and data types. As discussed, that polymorphism is of different types, for it to cover different types of data. Nd polymorphism has properties and methods.

What is meant by the polymorphism?

Definition of polymorphism : the quality or state of existing in or assuming different forms: such as. a(1) : existence of a species in several forms independent of the variations of sex. (2) : existence of a gene in several allelic forms also : a variation in a specific DNA sequence.


2 Answers

You generally do it with function pointers. In other words, simple structures that hold both the data and pointers to functions which manipulate that data. We were doing that sort of stuff years before Bjarne S came onto the scene.

So, for example, in a communications class, you would have an open, read, write and close call which would be maintained as four function pointers in the structure, alongside the data for an object, something like:

typedef struct {
    int (*open)(void *self, char *fspec);
    int (*close)(void *self);
    int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    // And the data for the object goes here.
} tCommsClass;

tCommsClass commRs232;
commRs232.open = &rs232Open;
: :
commRs232.write = &rs232Write;

tCommsClass commTcp;
commTcp.open = &tcpOpen;
: :
commTcp.write = &tcpWrite;

The initialisation of those function pointers would actually be in a "constructor" such as rs232Init(tCommClass*), which would be responsible for setting up the default state of that particular object to match a specific class.

When you 'inherit' from that class, you just change the pointers to point to your own functions. Everyone that called those functions would do it through the function pointers, giving you your polymorphism:

int stat = (commTcp.open)(commTcp, "bigiron.box.com:5000");

Sort of like a manually configured vtable, in C++ parlance.

You could even have virtual classes by setting the pointers to NULL -the behaviour would be slightly different to C++ inasmuch as you would probably get a core dump at run-time rather than an error at compile time.

Here's a piece of sample code that demonstrates it:

#include <stdio.h>

// The top-level class.

typedef struct _tCommClass {
    int (*open)(struct _tCommClass *self, char *fspec);
} tCommClass;

// Function for the TCP class.

static int tcpOpen (tCommClass *tcp, char *fspec) {
    printf ("Opening TCP: %s\n", fspec);
    return 0;
}
static int tcpInit (tCommClass *tcp) {
    tcp->open = &tcpOpen;
    return 0;
}

// Function for the HTML class.

static int htmlOpen (tCommClass *html, char *fspec) {
    printf ("Opening HTML: %s\n", fspec);
    return 0;
}
static int htmlInit (tCommClass *html) {
    html->open = &htmlOpen;
    return 0;
}

 

// Test program.

int main (void) {
    int status;
    tCommClass commTcp, commHtml;

    // Same base class but initialized to different sub-classes.
    tcpInit (&commTcp);
    htmlInit (&commHtml);

    // Called in exactly the same manner.

    status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
    status = (commHtml.open)(&commHtml, "http://www.microsoft.com");

    return 0;
}

This produces the output:

Opening TCP: bigiron.box.com:5000
Opening HTML: http://www.microsoft.com

so you can see that the different functions are being called, depending on the sub-class.

like image 173
paxdiablo Avatar answered Oct 04 '22 03:10

paxdiablo


I'm astonished, does no one have mentioned glib, gtk and the GObject system. So instead of baking yet-another-oo-layer-upon-C. Why not use something that has proofed to work?

Regards Friedrich

like image 24
Friedrich Avatar answered Oct 04 '22 04:10

Friedrich