This question already has answers here:
Object-orientation in C
(23 answers)
Closed 8 years ago.
Is it possible to model inheritance using C? How? Sample code will help.
Edit: I am looking to inherit both data and methods. Containership alone will not help. Substitutability - using any derived class object where a base class object works - is what I need.
It is very simple to go like this:
struct parent {
int foo;
char *bar;
};
struct child {
struct parent base;
int bar;
};
struct child derived;
derived.bar = 1;
derived.base.foo = 2;
But if you use MS extension (in GCC use -fms-extensions flag) you can use anonymous nested structs and it will look much better:
struct child {
struct parent; // anonymous nested struct
int bar;
};
struct child derived;
derived.bar = 1;
derived.foo = 2; // now it is flat
You can definitely write C in a (somewhat) object-oriented style.
Encapsulation can be done by keeping the definitions of your structures
in the .c file rather than in the associated header.
Then the outer world handles your objects by keeping pointers to them,
and you provide functions accepting such pointers as the "methods"
of your objects.
Polymorphism-like behavior can be obtained by using functions pointers,
usually grouped within "operations structures",
kind of like the "virtual method table" in your C++ objects
(or whatever it's called).
The ops structure can also include other things such as
constants whose value is specific to a given "subclass".
The "parent" structure can keep a reference to ops-specific data
through a generic void* pointer.
Of course the "subclass" could repeat the pattern for multiple levels
of inheritance.
So, in the example below, struct printer is akin to an abstract class,
which can be "derived" by filling out a pr_ops structure,
and providing a constructor function wrapping pr_create().
Each subtype will have its own structure which will be "anchored"
to the struct printer object through the data generic pointer.
This is demontrated by the fileprinter subtype.
One could imagine a GUI or socket-based printer,
that would be manipulated regardless by the rest of the code
as a struct printer * reference.
printer.h:
struct pr_ops {
void (*printline)(void *data, const char *line);
void (*cleanup)(void *data);
};
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data);
void pr_printline(struct printer *pr, const char *line);
void pr_delete(struct printer *pr);
printer.c:
#include "printer.h"
...
struct printer {
char *name;
struct pr_ops *ops;
void *data;
}
/* constructor */
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data)
{
struct printer *p = malloc(sizeof *p);
p->name = strdup(name);
p->ops = ops;
p->data = data;
}
void pr_printline(struct printer *p, const char *line)
{
char *l = malloc(strlen(line) + strlen(p->name) + 3;
sprintf(l, "%s: %s", p->name, line);
p->ops->printline(p->data, l);
}
void pr_delete(struct printer *p)
{
p->ops->cleanup(p->data);
free(p);
}
Finally, fileprinter.c:
struct fileprinter {
FILE *f;
int doflush;
};
static void filepr_printline(void *data, const char *line)
{
struct fileprinter *fp = data;
fprintf(fp->f, "%s\n", line);
if(fp->doflush) fflush(fp->f);
}
struct printer *filepr_create(const char *name, FILE *f, int doflush)
{
static const struct ops = {
filepr_printline,
free,
};
struct *fp = malloc(sizeof *fp);
fp->f = f;
fp->doflush = doflush;
return pr_create(name, &ops, fp);
}
Yes, you can emulate heritance en C using the "type punning" technique. That is the declaration of the base class (struct) inside the derived class, and cast the derived as a base:
struct base_class {
int x;
};
struct derived_class {
struct base_class base;
int y;
}
struct derived_class2 {
struct base_class base;
int z;
}
void test() {
struct derived_class d;
struct derived_class2 d2;
d.base.x = 10;
d.y = 20;
printf("x=%i, y=%i\n", d.base.x, d.y);
}
But you must to declare the base class in the first position in you derived structure, if you want to cast the derived as base in a program:
struct base *b1, *b2;
b1 = (struct base *)d;
b2 = (struct base *)d2;
b1->x=10;
b2->x=20;
printf("b1 x=%i, b2 x=%i\n", b1->x, b2->x);
In this snippet you can use the base class only.
I use this technique in my projects: oop4c
It should be possible, at least to some extent.
What exactly do you need to model? The inheritance of the data or the methods?
Edit: Here's a short article that I found: http://fluff.info/blog/arch/00000162.htm
I've used an object system in C that used late-bound methods, which allowed for object-orientation with reflection.
You can read about it here.
#include <stdio.h>
///////Class Cobj
typedef struct Cobj{
int x;
void (*setptr)(char * s,int val);
int (*getptr)(char * s);
} Cobj;
void set(char * s,int val)
{
Cobj * y=(Cobj *)s;
y->x=val;
}
int get(char * s){
Cobj * y=(Cobj *)s;
return y->x;
}
///////Class Cobj
Cobj s={12,set,get};
Cobj x;
void main(void){
x=s;
x.setptr((char*)&x,5);
s.setptr((char*)&s,8);
printf("%d %d %d",x.getptr((char*)&x),s.getptr((char*)&s) ,sizeof(Cobj));
}
This link might be useful -> link
Basic example will be like follow
struct BaseStruct
{
// some variable
}
struct DerivedStruct
{
struct BaseStruct lw;
// some more variable
};
Related
I have a c struct that has a const variable.
typedef struct {
u32 status;
const u32 dir_search_idx;} FS_OBJ;
What I would like to do is init the const variable in a function once I have created the struct object. I guess I want to do something similar to what a constructor would do in c++. Is it possible to do something similar in c? Thanks
This should work perfectly fine if you are using C99 or newer and want to initialize the const variable when creating the struct:
FS_OBJ obj = { .status = /* something */, .dir_seach_idx = /* something */ };
You can't modify the const variable after creating the struct. Then you would have to remove the const keyword as mentioned by user3386109 in the comments.
I think const is not the right tool for what you are looking for. You can put data (structs) and behavior (functions) in a *.c file and provide public functions in the corresponding header file. This way you can mimic the equivalent c++ code that you want and hide the data and of course, you can define a constructor. A great book that might help is The GLib/GTK+ Development Platform. In chapter 3 you can find a good introduction to Semi-Object-Oriented Programming in C.
Here is a possible implementation, not necessarily the best one:
/src/main.c
#include <stdio.h>
#include "point.h"
int main()
{
Point *p1 = init(6, 7);
printf("%d\n", getX(p1));
printf("%d\n", getY(p1));
Point *p2 = init(12, 14);
printf("%d\n", getX(p2));
printf("%d\n", getY(p2));
setX(p2, 16);
printf("%d\n", getX(p2));
setY(p2, 16); /* error; we want y to initialize once and remain constant. Also accessing y with p2->y is an error too. */
printf("%d\n", getY(p2)); /* getY is ok */
freep(p1);
freep(p2);
}
/src/point.h
typedef struct _Point Point;
Point *init(int, int);
int getX(Point *);
void setX(Point *, int);
int getY(Point *);
void freep(Point *);
/src/point.c
#include <stdlib.h>
#include "point.h"
struct _Point{
int x;
int y;
};
Point *init(int x, int y)
{
Point *temp;
temp = malloc(sizeof(Point));
temp->x = x;
temp->y = y;
return temp;
}
int getX(Point *p)
{
return p->x;
}
void setX(Point *p, int x)
{
p->x = x;
}
int getY(Point *p)
{
return p->y;
}
void freep(Point *p)
{
free(p);
}
Furthermore, if we need a private method in our class, we do not provide a declaration of it in the header and also we use static to restrict its access within the class's file.
I'm trying to setup a system where I pass around a pointer to a structure while hiding the definition of the structure from the end user. I have two options that seem to work, but I don't know if I'm making this harder than it needs to be, missing a trade off, or just doing something really stupid. I am stuck with C for any approach and can't use C++. Additionally, this will eventually need to talk to a Fortran program through, and I'm trying to make that as straightforward as possible.
I have a little utility to demonstrate the concept. Option one uses a void pointer to a pointer so that I can return a status integer from the function, if necessary. However, I don't like having to malloc before the call as I'm concerned about the Fortran side of things. This may be unfounded as I haven't done that demo, yet. Option two just returns a void pointer from the function, but I lose the ability to do a status return that way. With both versions, I do have a custom free function, even if not necessarily with the exact current implementation. The struct has it's own void pointer that will be defined based off the option input, and it will need to free that as part of the teardown process.
#include <stdio.h>
#include <stdlib.h>
struct State
{
int type;
void *data;
};
int Init1(int option, void **state);
void* Init2(int option);
void printState(void *state);
void free1(void **state);
void free2(void *state);
void* allocateData(int option);
int main(int argc, char *argv[])
{
void **ps1;
void *s2;
int ret;
ps1 = malloc(sizeof(void*));
ret = Init1(1, ps1);
printState(*ps1);
free1(ps1);
s2 = Init2(2);
printState(s2);
free2(s2);
return 0;
}
int Init1(int option, void **state)
{
(*state) = malloc(sizeof(struct State));
struct State* ret = *state;
ret->type = option;
return 0;
}
void free1(void **state)
{
free(*state);
free(state);
}
void* Init2(int option)
{
struct State* ret = malloc(sizeof(struct State));
ret->type = option;
return ret;
}
void free2(void *state)
{
free(state);
}
void printState(void *state)
{
struct State* data = state;
printf("Type : %d\n", data->type);
}
Look to the FILE type in stdio.h as an example. You can expose the type name without exposing its definition:
/**
* State.h
*/
#ifndef STATE_H
#define STATE_H
/**
* Create a typedef name for the *incomplete* type "struct State"
*/
typedef struct State STATE;
/**
* Define your interface
*/
void Init1( int, STATE ** );
STATE *Init2( int );
void printState( STATE * );
void sFree( STATE * );
void sFree2( STATE ** );
#endif
Then you complete the definition of the type in the implementation file:
/**
* State.c
*/
#include "State.h"
#include <stdlib.h>
...
/**
* Complete the type definition
*/
struct State {
int type;
void *data;
};
/**
* Implement the interface
*/
int Init1( int option, STATE **s )
{
*s = malloc ( sizeof **s ); // type definition is complete at this
if ( *s ) // point so we can use sizeof
{
(*s)->type = option;
}
return *s != NULL; // I'm *assuming* you want to return true (1)
} // if the allocation is successful
...
Now, when it comes to interoperating with Fortran ... I can't be that much help. I did that, once, on a VAX, 30-some-odd years ago, and it didn't involve opaque types like this.
I am a young student who learned C two years ago. I just discovered more complex things like object oriented C.
My first question is:
1) How do you access your variables? The goal would be to have specific values for those variables depending on the struct which has been instantiated.
So I'd like something like:
myStruct* myStrPtr;
myStruct2* myStrPtr;
myStrPtr = initializeStruct();
myStrPtr->printContent //prints for example 55
myStrPtr2 = initializeStruct();
myStrPtr2->printContent //prints for example 6548
example
typedef struct {
void (*sum)(int a, int b);
void (*printContent)(void);
int content;
}myStruct;
void printInhoud(void){
printf("content: %d\n", content);}
void sum(int a, int b){
/***********THIS DOESN T WORK OBVIOUSLY************/
this->content = a+b;
printf("calculated sum: %d", sum);
}
myStruct * initializeStruct(void)
{
myStruct* myStrPtr = malloc(sizeof(myStruct));
myStrPtr -> foo = foo ;
mynStrPtr->printContent = printContent;
return myStrPtr;
}
void freeMem(myStruct * myStructPtr)
{
free(myStructPtr);
}
int main (void)
{
int a= 1;
int b=33;
myStruct* myStrPtr;
myStrPtr = initializeStruct();
myStrPtr->printContent();
return 0;
}
2) my second question is: what are pro's and con's about programming in this way? I think that if I am able to add the variables in the structures and access them just like in OOP, I get a big advantage: modularity. I am active in embedded software and believe that having such an advantage of OOP on an embedded system can be very interesting. I have been criticized for trying to do this. The only reason I was given: "You have no garbage collector, so don't". Could someone give me some pro's and con's and explain why this would be "such an incredibly bad programming practice"
You can do OOP in C, but one of the major cons is that you have to pass the this pointer around. Let's say you have a pointer to a printInfo() function in your struct and you want to print the info of that particular struct. You have to do
my_struct->printInfo(my_struct);
or, if my_struct is not a pointer to your struct
my_struct.printInfo(&my_struct);
There's no way around it.
For your second question, I'm not sure doing OOP in C is really practical. I have done it out of curiosity and it's really fun. You can get inheritance, virtual base classes, polymorphism and all. If you're interested you can check it out here:
https://github.com/vladcc/object-oriented-c
Disclaimer: I'm not sure that the following is truely an answer, but it is way too long for a comment.
Is it possible to do OOP in C?
Yes it is. First C++ compilers were mere pre-processors that converted C++ source to C. Of course, you have neither contructors not destructors so you must explicitely call them, you must use composition pattern for inheritance, you must have vtables for virtual methods and must explicitely pass the this pointer.
Simple example with ctor, dtor, a dynamic array and a method:
struct __foo {
int *arr;
int n;
};
typedef struct __foo foo;
bool init_foo(foo *f, int n) {
f->arr = malloc(n * sizeof(int));
f->n = n;
return (f->arr != NULL);
}
void clean_foo(foo *f) { free(f->arr); }
bool set(int index, int value, foo *f) { // same for get...
if ((index >= f->n) || (index < 0)) return false;
f->arr[index] = value;
return true;
}
Usage:
foo f;
init_foo(8, &f);
set(5, 2, &f);
clean_foo(&f);
More complex example with inheritance and virtual method :
typedef struct {
int age;
const char *name;
const char* (*say)(void *);
} animal;
typedef struct {
animal parent;
} dog;
typedef struct {
animal parent;
} cat;
void init_animal(int age, const char *name, animal *a) {
a->age = age;
a->name = name;
}
char *pre_say(animal *this) {
char * msg = malloc(strlen(this->name) + 11);
strcpy(msg, this->name);
strcat(msg, " says ");
return msg;
const char * wow(void *an) {
animal *this = (animal *) an;
char * msg = pre_say(this);
strcat(msg, "Woof");
return msg;
}
const char* meeow(void *an) {
animal *this = (animal *) an;
char * msg = pre_say(this);
strcat(msg, "Meew");
return msg;
}
void init_dog(int age, const char * name, dog *d) {
init_animal(age, name, &(d->parent));
d->say = &woof;
}
void init_cat(int age, const char * name, cat *c) {
init_animal(age, name, &(c->parent));
d->say = &meeow;
}
Usage example:
dog d;
init_dog(2, "Rintintin", &d);
cat c;
init_cat(3, "Tom", &c);
const char *msg = (d.say)(&d); // msg <- Rintintin says Woof
free(msg);
msg = (c.say)(&c); // msg <- Tom says Meew
free(msg);
Should we do OOP in C?
Definitely NO. As you can say from previous example, as soon as you need polymorphism, pointers must be void * and you loose all possible type checking. And you also loose all the C++ goodies of automatic construtors and destructors, automatic this pointer, etc. You end with much more code, much harder to read and debug. The only acceptable use cases (IMHO) are:
interfacing C++ and C
minimal conversion of C++ code for a platform where you have only a C compiler.
low level codes (kernel or high performance libraries) in which you do not want to be bored with the overhead of C++, and still need OOP.
And just remember: if C++ was invented, it must have been to fill a gap in C language. So don't try to do what C++ was created for in C, unless you really know why you do that.
Has Garbage Collector something to do with OOP?
Here again no. C++ has no garbage collection and is indeed an OO language.
Not only encapsulation, many other OOP concepts can be implemented using C with little bit effort.
Here is an example.
//
// cobj.h
//
#ifndef __COBJ_H__
#define __COBJ_H__
struct _cobj_priv;
typedef struct _cobj {
struct _cobj_priv *priv;
void (*set_data)(struct _cobj *obj, int data);
int (*get_data)(struct _cobj *obj);
void (*print_data)(struct _cobj *obj);
} cobj_t;
cobj_t *new_struct(void);
void free_struct(cobj_t *obj);
#endif /* __COBJ_H__ */
//
// cobj.c
//
#include "cobj.h"
#include <stdio.h>
#include <stdlib.h>
//
// Internal section
//
struct _cobj_priv {
int data;
};
static void set_data (struct _cobj *obj, int data) {
struct _cobj_priv *this = (obj && obj->priv) ? obj->priv: NULL;
if (this) {
this->data = data;
}
}
static int get_data (struct _cobj *obj) {
struct _cobj_priv *this = (obj && obj->priv) ? obj->priv: NULL;
return (this)? this->data : 0;
}
static void print_data (struct _cobj *obj) {
struct _cobj_priv *this = (obj && obj->priv) ? obj->priv: NULL;
if (this)
printf("%d\n", this->data);
}
//
// APIs section
//
cobj_t *new_struct(void) {
cobj_t *obj = malloc(sizeof(cobj_t));
if (obj) {
obj->priv = malloc(sizeof(struct _cobj_priv));
if (obj->priv) {
obj->priv->data = 0;
}
obj->set_data = &set_data;
obj->get_data = &get_data;
obj->print_data = &print_data;
}
return obj;
}
void free_struct(cobj_t *obj) {
if (obj) {
if (obj->priv)
free(obj->priv);
free(obj);
obj = null;
}
}
//
// main.c
//
#include "cobj.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
cobj_t *obj = new_struct();
if (obj) {
obj->print_data(obj);
obj->set_data(obj, 100);
obj->print_data(obj);
printf("> get data return %d\n", obj->get_data(obj));
}
return 0;
}
Result:
0
100
> get data return 100
In C, struct's methods are function pointers, they do not know about the existence of struct so that they can not access to the struct members. You need to pass the struct instance to methods as a parameter in order to access to its members.
To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...
I am trying to change my C functions of nested structures to operate on pointers instead of passing and making copies of the structures which are quite large in reality.
here is a simplified version of what I want to do passing the structures around....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
outer1 = get_outer ();
}
struct OuterStruct get_outer (void)
{
struct OuterStruct thisOuter;
thisOuter.inner1 = get_inner (void);
thisOuter.outerResult = get_result (thisOuter.inner1);
return thisOuter;
}
struct InnerStruct get_inner (void)
{
struct InnerStruct thisInnner;
thisInner.int1 = 1;
thisInner.int2 = 2;
return thisInner;
}
int get_result (struct InnerStruct thisInner)
{
int thisResult;
thisResult = thisInner.int1 + thisInner.int2;
return thisResult;
}
but the structure is quite large in reality and this is a frequent operation, so I'd rather pass around the pointers. Just not sure how the syntax works for nested structures like this. Here is my attempt....
struct InnerStruct
{
int int1;
int int2;
};
struct OuterStruct
{
struct innerStruct inner1;
int outerResult;
};
void main (void)
{
struct OuterStruct outer1;
get_outer (&outer1);
}
void get_outer (struct OuterStruct *thisOuter)
{
get_inner (&(thisOuter->inner1));
thisOuter->outerResult = get_result (&(thisOuter->inner1));
}
void get_inner (struct InnerStruct *thisInner)
{
thisInner->int1 = 1;
thisInner->int2 = 2;
}
int get_result (struct OuterStruct *thisInner)
{
int thisResult;
thisResult = thisInner->int1 + thisInner->int2;
return thisResult;
}
You should really look up more about how pointers work. But here is some sample C++ code. Notice the "&" tells your compiler to "not send the struct itself" to the function but a pointer to it. Just a warning never return a reference to a variable (unless you know what you are doing).
#include <iostream>
struct MyStruct
{
int a;
int b;
};
using namespace std;
void printStruct(MyStruct * mypointer) {
cout << "MyStruct.a=" << mypointer->a << endl;
cout << "MyStruct.b=" << mypointer->b << endl;
}
int main()
{
MyStruct s;
s.a = 2;
s.b = 1;
printStruct(&s);
return 0;
}
This will illustrate an easy way to pass pointers to structs. It is a much more efficient way to pass data around, especially when, as you say, the data can get very large. This illustration uses a compound struct, (struct within struct) with an array and pointer declared to pass around. Comments in code explain things.
This will all build and run so you can experiment with it. i.e., follow the data along with execution.
Here is an easy way: (using my own structs)
typedef struct {
int alfha;
int beta;
} FIRST;
typedef struct {
char str1[10];
char str2[10];
FIRST first;
}SECOND; //creates a compound struct (struct within a struct, similar to your example)
SECOND second[5], *pSecond;//create an array of SECOND, and a SECOND *
SECOND * func(SECOND *a); //simple func() defined to illustrate struct pointer arguments and returns
int main(void)
{
pSecond = &second[0]; //initialize pSecond to point to first position of second[] (having fun now)
SECOND s[10], *pS; //local copy of SECOND to receive results from func
pS = &s[0];//just like above;
//At this point, you can pass pSecond as a pointer to struct (SECOND *)
strcpy(pSecond[0].str2, "hello");
pS = func(pSecond);
// printf("...", pS[0]...);//pseudo code - print contents of pS, which now contains any work done in func
return 0;
}
SECOND * func(SECOND *a) //inputs and outputs SECOND * (for illustration, i.e., the argument contains all
{ //information itself, not really necessary to return it also)
strcpy(a[0].str1, "a string");
return a;
}
Although there is not much going on in func(), when the pointer returns to main(), it contains both the value copied in main, and the value copied in fucn(), as shown here:
Results: (in code)
Contents in pSecond: