-
OOP in C
I would like to know what you think of object-oriented programming in pure C. Has someone ever used it in a true project and not just for the fun?
I'm not here to learn about how to, I already tested myself ^^ as I think it is something of interest at least for knowledge purpose.
Because of its lack of native support for OOP, each author can have its own vision of OOC.
Anyway, the true question is, what to you is the best way of doing OOP in C, which method do you use?
-
In my work we use object orientation a lot. The language of use is very often C, since often we have to deal with processors for which no C++ compiler is available or our customers want us to use C since they use C.
There are several ways to implement object oriented designs in C, the following I still find very effective. It makes use of interfaces, which are defined in header files. The implementations of those interfaces are done in source files. An object oriented principle like inheriting can be done by inheriting an interface.
-
Would you mind telling me more about the way you do inheritance, multiple inheritance and polymorphism?
-
Interfaces are defined in a header-file. Assume there is a class called Class_A and there is a class called Class_B. Then we could define the interfaces to these classes in header files and implement those interfaces in source files.
Now we want a class Class_C, which inherits from Class_A. Then we will do this by inheriting the interface. We can include the interface header file of Class_A in the interface header file of Class_C. When implementing Class_C, then we know about the interface of Class_A and can use this interface. In this way we can make use of functionality (services) provided by Class_A without knowing how Class_A has implemented its services and its datastructures. An important concept in object orientation.
Now we want a class Class_D, which inherits from Class_C and Class_B. We can do this be including the interface header files of Class_C and Class_B in the interface header file of Class_D. When implementing the interface of Class_D, we can make use of the services of the other classes.
This is in short how we do it.
I recently read an article about another way of implementing inheritance in C. Here's some code from that article.
First they defined a class called Signal and they defined an interface for it, called SignalInterface.
Code:
typedef struct Signal Signal;
typedef struct SignalInterface SignalInterface;
struct SignalInterface
{
// The signal.
Signal *signal;
// Destructor.
void (*destroy)(SignalInterface *signal);
// Interface functions.
int (*setSample)(SignalInterface *signalInterface, int index, int newValue);
int (*getSample)(SignalInterface *signalInterface, int index);
int (*resetSample)(SignalInterface *signalInterface, int index);
int (*resetSignal)(SignalInterface *signalInterface);
};
Then they defined their own interface called MySignalInterface. This interface inherits the interface SignalInterface. In their own interface, they added one signal. For
Code:
typedef struct MySignalInterface MySignalInterface;
struct MySignalInterface
{
// Inherit from Signal interface.
SignalInterface *signalInterface;
// Destructor.
void (*destroy)(MySignalInterface *mySignalInterface);
// Add new member function.
int (*invertSignal)(SignalInterface *signalInterface);
};
Here's a shortened version of the main() program they used to test. In my opinion it is not a very elegant solution for object orientation in C, because when using the interface MySignalInterface, the programmer has to know about the interface SignalInterface, which in my opinion is not very elegant. I think it would be more elegant if the MySignalInterface provided an interface to the interface functions within SignalInterface.
Code:
#include <stdio.h>
#include "MySignalInterface.h"
int main ()
{
MySignalInterface *mySignal;
int i, j;
mySignal = createMySignal ();
printf ("MAIN: Signal created\n");
for (i = 0; i < 10; i++)
{
printf ("MAIN: Set sample %d\n", i);
mySignal->signalInterface->setSample (mySignal->signalInterface, i, i);
}
for (i = 0; i < 10; i++)
{
j = mySignal->signalInterface->getSample (mySignal->signalInterface, i);
printf ("MAIN: Retrieved sample %d value %d\n", i, j);
}
i = mySignal->invertSignal (mySignal->signalInterface);
printf ("MAIN: Result of inversion %d\n", i);
for (i = 0; i < 10; i++)
{
j = mySignal->signalInterface->getSample (mySignal->signalInterface, i);
printf ("MAIN: Retrieved sample %d value %d\n", i, j);
}
mySignal->destroy (mySignal);
return 0;
}
-
Shiro, thank you very much for explaining your "OOP in C"-technique. That's exactly what I've been looking for.
I've been working on a new version of my scientific project for months. I am still in the brainstorming phase. During the last weeks I've been thinking a lot about how I could move the data between functions of different libraries. And your interfaces/classes are the solution in my (very) special case.
Thanks again! :)
P.S.: If you happen to have a link to a website at hand that elaborates further on your OOP technique, it would be greatly appreciated.