Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
When I am presented with programming problems, I naturally start breaking them up into logical objects in my head. Who has what responsibility, who owns what, who derives from what, etc.
I am struggling with C. I just don't get how to do things in a Procedural Language.
Can an experienced C programmer help explain how I should think about my programs during design time?
For example, I want to write my own Semaphore class. I would naturally need a Queue data structure for my program, which I would like to write myself as well. If I needed to do this in Java or C#, I could simply whip up a quick Queue class and create a new instance of it in my Semaphore class.
But in C, there aren't objects. So do I have to inline all the behavior of my Queue data structure?
Can someone help me "get it"?
Related: what is the best way to plan and organize development of an application in c
But in C, there aren't objects. So do
I have to inline all the behavior of
my Queue data structure?
No.
Do this.
Define your class however you feel comfortable doing OO design.
Write the attributes of your class as a C-language struct.
Put that struct in a header file, along with all of the functions that operate on that struct. Make sure a MyStruct * self is the first argument to all of these "method functions".
Write a C module with all of the bodies of the method functions.
Poor-person's OO in C. It works well. Just be disciplined about putting everything into the struct that you need -- public and private instance variables -- everything.
Generally, avoid trying to have private variables in the first place. You don't have the full power of an OO compiler, so don't bother with low-value features like "private" or "protected".
I would amend S. Lott's answer to use an opaque pointer to perform data hiding of the members of the struct:
Define your class however you want using normal OO design.
Member variables of your class go into a C language struct.
In the header file, you do not want to expose the member variables of your object (since these would be "private" in an OO language). Instead, use an opaque pointer, i.e.
typedef struct mystruct_s *mystruct_t; // first argument to all your methods
For all the methods you want to be "public", put their signatures in your .h file. Method bodies should go into the .c file, and "private" methods should be only defined in the .c file and also declared static so their symbols do not collide with symbols defined in other files.
Clever naming conventions like underscores are unnecessary using this method, but it means that all your member variables will be private. Functions can be public or private, although public functions they are part of a global namespace so you might want to qualify their names with a "package" name like mystruct_push(), mystruct_pop(), etc.
You also need to make it clear if the caller or the library is responsible for calling malloc() and free(). Most likely you will have mystruct_t *create() and void destroy(mystruct_t *target) methods.
You can still think object oriented with C.
You just need to create a struct and a set of functions that take a pointer to an instance of that struct as its first parameter.
As for polymorphism, you can pass the size of the struct as the first member of the struct, so you know how to cast it.
There is a great pdf of object oriented programming with ANSI-C here.
I had a bear of a time moving from procedural to OO thinking, so I feel your pain.
I found that in order to learn how to create objects, it was best to think about how they would look to the caller. The same approach might help you, going the other way. Consider what the API to your component would look like. One good way is to study existing C APIs (I used the standard Java APIs as a set of examples of an OO API).
You're used to using a queue component something like this:
import some.package.Queue;
Queue q = new Queue();
q.add(item);
In a typical C api, you'd expect something more like:
#include <queue.h> // provides queue, make_queue(), queue_add(), others
queue q = make_queue(); // queue is probably a struct, or a struct*
queue_add(q,item);
Whenever you find yourself thinking in objects, make a similar transform.
You can use pointers to functions and the like, to make object-like structures in C - but many thousands of C programmers have managed without.
Good luck!
Check out the Lua C api. It has been my guiding light as far as C interface design goes. Every function takes a Lua state as a leading argument which becomes your "this". Inheritance is a little trickier but Chipmunk manages to do a pretty good job exposing functions that take a generic shape structs and work out the details of which function is actually called via a "klass". You can often exploit void* to have functions take different types (structs) the way you would overload in OO. It can feel a little hackish at times but works well.
Originally C++ was just a compiler that wrote C code from the C++ sources; those were then compiled by the native C compiler, linked, etc.
Hence, all OOP methods are available in C -- it's just that the compiler won't help you, and does not provide all the compile-time capabilities such as templates, operator overrides, data hiding, etc.
The C++ "struct" was (probably still is) equivalent to a "class" with all members "public".
Member functions can be implemented as function pointers in a structure; this can provide encapsulation and polymorphism. Constructors exist in the global scope unless you're using factories. Destructors can be member functions.
Using accessor member functions, like getColor(), setColor() can alleviate internal differences and provide some data hiding. If you really want, you could use Brian Bondy's suggestion of hiding with macros.
There are actually a lot of FOSS libraries that provide standard containers -- hash tables, dynamic arrays, linked lists, etc.
I second the suggestions for doing "Poor man's OO in C." I also think you might benefit from taking some time to see how Perl's OO works. Basically OO is accomplished in Perl by having the interpreter supply every method with the instance as an implicit first parameter. You'll want to do the same in C, explicitly, and use really, really good code organization since the compiler will not enforce good encapsulation for you.
By the way, you can enforce keeping the members of your structs private by using opaque pointers. I seem to recall that the GNU programming standards and recommendations included a technique for doing this by basically casting everything to void* when it was passed around, then using typedefs to name each specific type of opaque pointer that was supposed to be passed. (i.e., each "class")
You can do derived classes also with C:
Derived classes in C - What is your favorite method?
use glib, c library with oop
http://library.gnome.org/devel/glib/2.20/
Related
I recently transferred into a different school & cs program. The language used is C as compared to java which was taught at my previous school. One of my main issues which may be the result of not writing enough C code is that I'm having trouble finding a standard for making Abstract Data Types.
From what I've seen, there are tons of ways these are implemented and the lack of a visible standard is making me worried I missed something while self learning C. I've seen implementations that hide the init variable from the user such as
#define createVector(vec) Vector vec; void init_vector(&vec)
and another version which is what I would be more used to in which a handle is used to hold the returned pointer to struct from the createVector() function. The issue is I can't find any detailed description on handles online or in my course 2 book. The course 2 book only shows the interface and methods but not how they are grouped together in a way that hides the implementation from the user. I wanted to know if there was a "correct" way/standard for ADTs? The book in question is Robert Sedgewick "Algorithms in C - Third Edition".
Abstract Data Types
Split your sources.
The header (.h files) contains the abstract declarations like the datatypes (structs, functions, enums, constants, etc)
The actual implementation is done in the .c files.
When using such a (lets call it) module you only include the header in your source.
The implementiation you use is decided at linking time. You may decide to use different .c files for implementation or a static library (or even a dynamic library).
If you want to hide the data you use opaque structures.
Why is this standard? Ever heard of the FILE type? This is the opaque type used for IO in c's standardlibrary. You only include the header stdio.h and leave the implementation to the compiler. The header on the other hand or at least the symbols that it defines are well documented (and part of the c standard).
Abstract Classes
Java has the concept of an abstract class. Well, it also has the concept of a class in general. C does not. This is more a personal opinion but don't waste time on emulating language features that the language does not offer.
For none abstract methods use functions which take a pointer to a (probably opaque) struct containing all the data needed as first parameter, like fprintf(FILE*,const char*,...).
For abstract methods you will need function pointers.
Use these function pointers (or maybe a struct of function pointers) like a strategy. You may define a method for registering such a strategyand delegate the normal functions to them. Take for example the atexit function, which globally (you may call it a singleton) adds a exiting-strategy.
The XY Problem
I'm having trouble finding a standard for making Abstract Data Types
Read about this and apply it to your question.
Instead of trying to force your solution to work rethink if the attempted solution is applicable to the problem. Try to get comfy with the techniques described above. This may need a bit of practice but then you can model your solution in a more c-styled way.
I just wanted to post this as I figured out the answer that would be more specific to my case however I understand that this probably doesn't apply to everyone. The thing I was looking for was the idea of "First Class ADTs" which use a handle to contain a pointer to the actual object that was created from a .c implementation file that would be hidden from the user.
For ADT using C, this approach is the standard as far as I know. You will have a header (.h) file and one or more implementation (.c) files. The header file might look something like:
typedef struct * Doodad;
Doodad * doodadInit(int);
void doodadDestroy(Doodad *);
int doodadGetData(Doodad *);
void doodadSetData(int);
For your implementation file(s) you might have:
typedef struct iDoodad {
int data;
} Doodad;
Doodad * doodadInit(int data) {
...
}
...
if I am developing a C shared library and I have my own structs. To make common operations on these struct instances easier for library consumers, can I provide function pointers to such functions inside the struct itself? Is it a good practice? Would there be issues with respect to multithreading where a utility function is called in parallel with different arguments and so on?
I know it goes a lot closer to C++ classes but I wish to stick to C and learn how it would be done in a procedural language as opposed to OOP.
To give an example
typedef struct tag tag;
typedef struct my_custom_struct my_custom_struct;
struct tag
{
// ...
};
struct my_custom_struct
{
tag *tags;
my_custom_struct* (*add_tag)(my_custom_struct* str, tag *tag);
};
my_custom_struct* add_tag(my_custom_struct* str, tag *tag)
{
// ...
}
where add_tag is a helper that manages to add the tag to tag list inside *str.
I saw this pattern in libjson-c like here- http://json-c.github.io/json-c/json-c-0.13.1/doc/html/structarray__list.html. There is a function pointer given inside array_list to help free it.
To make common operations on these struct instances easier for library
consumers, can I provide function pointers to such functions inside
the struct itself?
It is possible to endow your structures with members that are function pointers, pointing to function types whose parameters include pointers to your structure type, and that are intended to be used more or less like C++ instance methods, more or less as presented in the question.
Is it a good practice?
TL;DR: no.
The first problem you will run into is getting those pointer members initialized appropriately. Name correspondence notwithstanding, the function pointers in instances of your structure will not automatically be initialized to point to a particular function. Unless you make the structure type opaque, users can (and undoubtedly sometimes will) declare instances without calling whatever constructor-analog function you provide for the purpose, and then chaos will ensue.
If you do make the structure opaque (which after all isn't a bad idea), then you'll need non-member functions anyway, because your users won't be able to access the function pointers directly. Perhaps something like this:
struct my_custom_struct *my_add_tag(struct my_custom_struct *str, tag *tag) {
return str->add_tag(str, tag);
}
But if you're going to provide for that, then what's the point of the extra level of indirection? (Answer: the only good reason for that would be that in different instances, the function pointer can point to different functions.)
And similar applies if you don't make the structure opaque. Then you might suppose that users would (more) directly call
str->add_tag(str, tag);
but what exactly makes that a convenience with respect to simply
add_tag(str, tag);
?
So overall, no, I would not consider this approach a good practice in general. There are limited circumstances where it may make sense to do something along these lines, but not as a general library convention.
Would there be issues with
respect to multithreading where a utility function is called in
parallel with different arguments and so on?
Not more so than with functions designated any other way, except if the function pointers themselves are being modified.
I know it goes a lot closer to C++ classes but I wish to stick to C
and learn how it would be done in a procedural language as opposed to
OOP.
If you want to learn C idioms and conventions then by all means do so. What you are describing is not one. C code and libraries can absolutely be designed with use of OO principles such as encapsulation, and to some extent even polymorphism, but it is not conventionally achieved via the mechanism you describe. This answer touches on some of the approaches that are used for the purpose.
Is it a good practice?
TLDR; no.
Background:
I've been programming almost exclusively in embedded C on STM32 microcontrollers for the last year and a half (as opposed to using C++ or "C+", as I'll describe below). It's been very insightful for me to have to learn C at the architectural level, like I have. I've studied C architecture pretty hard to get to where I can say I "know C". It turns out, as we all know, C and C++ are NOT the same language. At the syntax level, C is almost exactly a subset of C++ (with some key differences where C supports stuff C++ does not), hence why people (myself included before this) frequently think/thought they are pretty much the same language, but at the architectural level they are VASTLY DIFFERENT ANIMALS.
Aside:
Note that my favorite approach to embedded is to use what some colloquially know as "C+". It is basically using a C++ compiler to write C-style embedded code. You basically just write C how you'd expect to write C, except you use C++ classes to vastly simplify the (otherwise pure C) architecture. In other words, "C+" is a pseudonym used to describe using a C++ compiler to write C-like code that uses classes instead of "object-based C" architecture (which is described below). You may also use some advanced C++ concepts on occasion, like operator overloading or templates, but avoid the STL for the most part to not accidentally use dynamic allocation (behind-the-scenes and automatically, like C++ vectors do, for example) after initialization, since dynamic memory allocation/deallocation in normal run-time can quickly use up scarce RAM resources and make otherwise-deterministic code non-deterministic. So-called "C+" may also include using a mix of C (compiled with the C compiler) and C++ (compiled with the C++ compiler), linked together as required (don't forget your extern "C" usage in C header files included in your C++ code, as required).
The core Arduino source code (again, the core, not necessarily their example "sketches" or example code for beginners) does this really well, and can be used as a model of good "C+" design. <== before you attack me on this, go study the Arduino source code for dozen of hours like I have [again, NOT the example "sketches", but their actual source code, linked-to below], and drop your "arduino is for beginners" pride right now.
The AVR core (mix of C and "C+"-style C++) is here: https://github.com/arduino/ArduinoCore-avr/tree/master/cores/arduino
Some of the core libraries ("C+"-style C++) are here: https://github.com/arduino/ArduinoCore-avr/tree/master/libraries
[aside over]
Architectural C notes:
So, regarding C architecture (ie: actual C, NOT "C+"/C-style C++):
C is not an OO language, as you know, but it can be written in an "object-based" style. Notice I say "object-based", NOT "object oriented", as that's how I've heard other pedantic C programmers refer to it. I can say I write object-based C architecture, and it's actually quite interesting.
To make object-based C architecture, here's a few things to remember:
Namespaces can be done in C simply by prepending your namespace name and an underscore in front of something. That's all a namespace really is after-all. Ex: mylibraryname_foo(), mylibraryname_bar(), etc. Apply this to enums, for example, since C doesn't have "enum classes" like C++. Apply it to all C class "methods" too since C doesn't have classes. Apply to all global variables or defines as well that pertain to a particular library.
When making C "classes", you have 2 major architectural options, both of which are very valid and widely used:
Use public structs (possibly hidden in headers named "myheader_private.h" to give them a pseudo-sense of privacy)
Use opaque structs (frequently called "opaque pointers" since they are pointers to opaque structs)
When making C "classes", you have the option of wrapping up pointers to functions inside of your structs above to give it a more "C++" type feel. This is somewhat common, but in my opinion a horrible idea which makes the code nearly impossible to follow and very difficult to read, understand, and maintain.
1st option, public structs:
Make a header file with a struct definition which contains all your "class data". I recommend you do NOT include pointers to functions (will discuss later). This essentially gives you the equivalent of a "C++ class where all members are public." The downside is you don't get data hiding. The upside is you can use static memory allocation of all of your C "class objects" since your user code which includes these library headers knows the full specification and size of the struct.
2nd option: opaque structs:
In your library header file, make a forward declaration to a struct:
/// Opaque pointer (handle) to C-style "object" of "class" type mylibrarymodule:
typedef struct mylibrarymodule_s *mylibrarymodule_h;
In your library .c source file, provide the full definition of the struct mylibrarymodule_s. Since users of this library include only the header file, they do NOT get to see the full implementation or size of this opaque struct. That is what "opaque" means: "hidden". It is obfuscated, or hidden away. This essentially gives you the equivalent of a "C++ class where all members are private." The upside is you get true data hiding. The downside is you can NOT use static memory allocation for any of your C "class objects" in your user code using this library, since any user code including this library doesn't even know how big the struct is, so it cannot be statically allocated. Instead, the library must do dynamic memory allocation at program initialization, one time, which is safe even for embedded deterministic real-time safety-critical systems since you are not allocating or freeing memory during normal program execution.
For a detailed and full example of Option 2 (don't be confused: I call it "Option 1.5" in my answer linked-to here) see my other answer on opaque structs/pointers here: Opaque C structs: how should they be declared?.
Personally, I think the Option 1, with static memory allocation and "all public members", may be my preferred approach, but I am most familiar with the opaque struct Option 2 approach, since that's what the C code base I work in the most uses.
Bullet 3 above: including pointers to functions in your structs.
This can be done, and some do it, but I really hate it. Don't do it. It just makes your code so stinking hard to follow. In Eclipse, for instance, which has an excellent indexer, I can Ctrl + click on anything and it will jump to its definition. What if I want to see the implementation of a function I'm calling on a C "object"? I Ctrl + click it and it jumps to the declaration of the pointer to the function. But where's the function??? I don't know! It might take me 10 minutes of grepping and using find or search tools, digging all around the code base, to find the stinking function definition. Once I find it, I forget where I was, and I have to repeat it all over again for every single function, every single time I edit a library module using this approach. It's just bad. The opaque pointer approach above works fantastic instead, and the public pointer approach would be easy too.
Now, to directly answer your questions:
To make common operations on these struct instances easier for library consumers, can I provide function pointers to such functions inside the struct itself?
Yes you can, but it only makes calling something easier. Don't do it. Finding the function to look at its implementation becomes really hard.
Is it a good practice?
No, use Option 1 or Option 2 above instead, where you now just have to call C "namespaced" "methods" on every C "object". You must simply pass the "members of the C class" into the function as the first argument for every call instead. This means instead of in C++ where you can do:
myclass.dosomething(int a, int b);
You'll just have to do in object-based C:
// Notice that you must pass the "guts", or member data
// (`mylibrarymodule` here), of each C "class" into the namespaced
// "methods" to operate on said C "class object"!
// - Essentially you're passing around the guts (member variables)
// of the C "class" (which guts are frequently referred to as
// "private data", or just `priv` in C lingo) to each function that
// needs to operate on a C object
mylibrarymodule_dosomething(mylibrarymodule_h mylibrarymodule, int a, int b);
Would there be issues with respect to multithreading where a utility function is called in parallel with different arguments and so on?
Yes, same as in any multithreaded situation where multiple threads are trying to access the same data. Just add a mutex to each C struct-based "object", and be sure each "method" acting on your C "objects" properly locks (takes) and unlocks (gives) the mutex as required before operating on any shared volatile members of the C "object".
Related:
Opaque C structs: how should they be declared? [use "Object-based" C architecture]
I would like to suggest you reading com specification, you will gain a lot. all these com, ole and dcom technology is based on a simple struct that incorporates its own data and methods.
https://www.scribd.com/document/45643943/Com-Spec
simplied more here
http://www.voidcn.com/article/p-fixbymia-beu.html
Somebody can give me an example to do this. Suppose static variable scope is limited to file only.That is private to that file.Like that some more examples i want to know. In other words HOW TO ACHIEVE DATA HIDING CONCEPT IN C-LANGUAGE WITH CURRENTLY AVAILABLE KEYWORDS(STRUCT,STATIC...ETC)
This guy is one of the worlds authorities on embedded systems. He wrote this white paper on OOP in c.
http://www.state-machine.com/resources/cplus_3.0_manual.pdf
You can use a private header (say xyz_private.h) where you define your private structs (say struct xyz_private_t). In the public header you canthen do
typedef struct xyz_private_t *xyz_ptr_t; or
typedef struct {
... some public members ...
struct xyz_private_t *private;
} mytype_t;
This is similiar to PIMPL in C++.
private, friend, protected can not be distinguished - either a file can/does access the private header or it can't/doesn't.
You would have to rewrite/extend the compiler, add new grammar to the lexigraphic unit (this is probably the easiest part) and most importantly, add new specs. If you would add these keywords to the C-Language, you wouldn't have the C-Language anymore, but a derivate. Your code wouldn't be understood by any other compiler. Also, those aren't just keywords, they are specific expected behaviour, you can't just implement the keywords, you'd have to add full OOP support to the language. If this is what you are planning - good luck.
Data-hiding is a feature of managed languages, because there is a runtime seperate to your program taking care of things behind the curtain, this does not exist in C. If you want to have these features (data-hiding and other abstractions limited to managed languages), you'd have to exactly produce such a construct, ie. implementing a runtime to take care of things behind the curtain. Then, and ONLY then, are you able to achieve data hiding and other abstractions.
C simply does not offer these possibilites, any code in the program can access any address in the virtual memory of the process, going around anything you are planing.
My advice, even if it will be hard for you: use a managed language for that. C isn't the right language to achieve what you want to do.
Yes, internal linkage (static) effectively makes things private to a file. You don't necessarily need that, though. You can simulate a class with private members by defining a struct inside the source file and providing only a typedef and a set of functions to your users. All of the functions, except for the "constructor" would take an explicit "this" argument. Your faux constructor would simply allocate an instance of your type and return the pointer. Since all your functions would be defined (with external linkage) in the same source as the struct, they can see the members. Your users who only see the typedef and function prototypes cannot.
You can use static in this case to emulate a singleton by having your functions return a pointer to your internally declared instance.
C++ originated as a pre-compiler for C with pre-compilers such as Glockenspiel and CFront. You may find what you are looking for here (it also provide sources).
If you don't pick up clues from there, I think the only way you can achieve true data-hiding in C is to declare your variables as static variables to functions.
Being a developer born and raised on OO, I was curious to hear how it's possible to avoid global state in a procedural program.
You can also write object-oriented code in C. You don't get all the C++ goodies and it's ugly, and you have to manually pass the this pointer (I've seen self used for this, in order to make it compatible with C++), but it works. So technically, you don't need global state in pure procedural languages for the very same reasons you don't need it in object-oriented languages. You just have to pass the state around explicitly, rather than implicitly like in OO languages.
As an example, look at how the file I/O functions in the C standard library work with pointer to FILE objects that are (largely) opaque. Or look at how OS APIs deal with handles and such to encapsulate information. A program creates objects, uses APIs that act on those objects and closes/deletes the objects - all using straight C.
A global variable is nothing but an implicit procedure argument. Make it explicit and the global variable goes away.
Note: the fact that you no longer use a global variable does not mean that you no longer use global state! What we did above was just a purely syntactical transformation, the semantics of the program haven't changed at all. It's just as non-composable, non-modular, non-threadsafe, non-parallelizable as it was before.
All OO is a mindset and a whole bunch of compiler support.
You can achieve much the same by discipline, coding conventions, and passing around structures in most languages.
For example I used to have functions/procedures prefixed with their module identity, taking the first parameter as being the related module struct.
// System.h
typedef struct _System
{
struct _System *owner;
LinkedList *elements;
} System;
// System.c
int System_FindName ( System * system, char *name)
{
..
}
etc..
I'd really seriously not like to have to go back to coding like this though. I'm very happy that I haven't had to write and debug a linked list for at least 18 years. It was hard back then without the internet and sitting there isolated in the corner of a cold brightly lit room with green phosphors burning into your retina...
Of course. Just declare a struct somewhere, allocate some memory for it, pass the pointer to the allocated memory to an initialization function, and off you go. Just pass the pointer to all the functions that require using the struct.
Though the question arises as to where you store the pointer to the data you don't want to be global, and then you may end up with a global pointer ;-)
You can have variables on stack or in heap that will exist during all the program life.
Passing object style structure pointers to every function is a good way to have OO C coding style.
(I would suggest to have a look in linux sources)
You could try, as an example, create with dia (the diagramming tool), a simple class (for example, a square).
http://projects.gnome.org/dia/
http://dia-installer.de/index_en.html
Then, you can transform that class in C code using dia2code:
http://dia2code.sourceforge.net/
Specifically, say you created the class square inside the square.dia diagram. Then, you type:
$ dia2code -t c square.dia
... and you will see that it is possible to convert any object-oriented programming in a C program without global variables. Explore the created files square.c and square.h
NOTE: in Windows, you'll need a workaround in order to make dia2code work. Before using dia2code, change square.dia to square.zip, unzip it, and rename the result as square.dia
Simple. Whenever a procedure accesses a global variable, then give this variable as an argument to the procedure instead, either by value or by reference or by pointer, or by whatever your programming language provides. After that there is no more need for the variable to be global.
This question already has answers here:
Object Oriented pattern in C? [duplicate]
(4 answers)
Closed 1 year ago.
Possible Duplicates:
Can you write object oriented code in C?
Object Oriented pattern in C ?
I remember reading a while ago about someone (I think it was Linus Torvalds) talking about how C++ is a horrible language and how you can write object-oriented programs with C. On having had time to reflect, I don't really see how all object oriented concepts carry over into C. Some things are fairly obvious. For example:
To emulate member functions, you can put function pointers in structs.
To emulate polymorphism, you can write a function that takes a variable number of arguments and do some voodoo depending on, say, the sizeof the parameter(s)
How would you emulate encapsulation and inheritance though?
I suppose encapsulation could sort of be emulated by having a nested struct that stored private members. It would be fairly easy to get around, but could perhaps be named PRIVATE or something equally obvious to signal that it isn't meant to be used from outside the struct. What about inheritance though?
You can implement polymorphism with regular functions and virtual tables (vtables). Here's a pretty neat system that I invented (based on C++) for a programming exercise:
The constructors allocate memory and then call the class's init function where the memory is initialized. Each init function should also contain a static vtable struct that contains the virtual function pointers (NULL for pure virtual). Derived class init functions call the superclass init function before doing anything else.
A very nice API can be created by implementing the virtual function wrappers (not to be confused with the functions pointed to by the vtables) as follows (add static inline in front of it, if you do this in the header):
int playerGuess(Player* this) { return this->vtable->guess(this); }
Single inheritance can be done by abusing the binary layout of a struct:
Notice that multiple inheritance is messier as then you often need to adjust the pointer value when casting between types of the hierarchy.
Other type-specific data can be added to the virtual tables as well. Examples include runtime type info (e.g. type name as a string), linking to superclass vtable and the destructor chain. You probably want virtual destructors where derived class destructor demotes the object to its super class and then recursively calls the destructor of that and so on, until the base class destructor is reached and that finally frees the struct.
Encapsulation was done by defining the structs in player_protected.h and implementing the functions (pointed to by the vtable) in player_protected.c, and similarly for derived classes, but this is quite clumsy and it degrades performance (as virtual wrappers cannot be put to headers), so I would recommend against it.
Have you read the "bible" on the subject? See Object Oriented C...
How would you emulate encapsulation and inheritance though?
Actually, encapsulation is the easiest part. Encapsulation is a design philosophy, it has nothing at all to do with the language and everything to to with how you think about problems.
For example, the Windows FILE api is completely encapsulated. When you open a file, you get back an opaque object that contains all of the state information for the file 'object'. You hand this handle back to each of the file io apis. The encapsulation is actually much better than C++ because there is no public header file that people can look at and see the names of your private variables.
Inheritance is harder, but it isn't at all necessary in order for your code to be object oriented. In some ways aggregation is better than inheritance anyway, and aggregation is just as easy in C as in C++. see this for instance.
In response to Neil see Wikipedia for an explanation of why inheritance isn't necessary for polymorphism.
Us old-timers wrote object oriented code years before C++ compilers were available, it's a mind-set not a tool-set.
Apple's C-based CoreFoundation framework was actually written so that its "objects" could double as objects in Objective-C, an actual OO language. A fairly large subset of the framework is open source on Apple's site as CF-Lite. Might be a useful case study in a major OS-level framework done this way.
From a little bit higher altitude and considering the problem rather more open-minded than as the OOP mainstream may suggest, Object-Oriented Programming means thinking about objects as of data with associated functions. It does not necessarily mean an function has to be physically attached to an object as it is in popular languages which support paradigm of OOP, for instance in C++:
struct T
{
int data;
int get_data() const { return data; }
};
I would suggest to take a closer look at GTK+ Object and Type System. It is a brilliant example of OOP realised in C programming language:
GTK+ implements its own custom object
system, which offers standard
object-oriented features such as
inheritance and virtual function
The association can also be contractual and conventional.
Regarding encapsulation and data hiding techniques, popular and simple one may be Opaque Pointer (or Opaque Data Type) - you can pass it around but in order to load or store any information, you have to call associated function which knows how to talk to the object hidden behind that opaque pointer.
Another one, similar but different is Shadow Data type - check this link where Jon Jagger gives excellent explanation of this not-so-well-known-technique.
the gtk and glib libraries use macros to cast objects to various types.
add_widget(GTK_WIDGET(myButton));
I can't say how it's done but you can read their source to find out exactly how it's done.
Take a look at the way the VFS layer works in the Linux kernel for an example of an inheritance pattern. The file operations for the various filesystems "inherit" a set of generic file operations functions (eg generic_file_aio_read(), generic_file_llseek()...), but can override them with their own implementations (eg. ntfs_file_aio_write()).
Definitely look at Objective-C.
typedef struct objc_object {
Class isa;
} *id;
typedef struct objc_class {
struct objc_class *isa;
struct objc_class *super_class
const char *name;
long version;
long info
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
} *Class;
As you can see, inheritance information, along with other details is held in a class struct (conveniently the class can also be treated as an object).
Objective-C suffers in the same manner as C++ with encapsulation in that you need to declare your variables publicly. Straight C is much more flexible in that you can just return void pointers that only your module has internal access to, so in that respect encapsulation is much better.
I once wrote a basic OO style C paint program as part of a graphics course - I didn't go as far as the class declaration, I simply used a vtable pointer as the first element of the struct and implemented hand-coded inheritance. The neat thing about playing around with vtables at such a low level is that you can change class behaviour at runtime by changing a few pointers, or change on objects class dynamically. It was quite easy to create all sorts of hybrid objects, fake multiple inheritance, etc.
Nice article & discussion regarding Objective-C here:
http://cocoawithlove.com/2009/10/objective-c-niche-why-it-survives-in.html
For a great example of object-oriented programming in C, look at the source of POV-Ray from several years ago - version 3.1g is particularly good. "Objects" were struct with function pointers, of course. Macros were used to provide the core methods and data for an abstract object, and derived classes were structs that began with that macro. There was no attempt to deal with private/public, however. Things to be seen were in .h files and implementation details were in .c files, mostly, except for a lot of exceptions.
There were some neat tricks that I don't see how could be carried over to C++ - such as converting one class to a different but similar one on the fly just by reassigning function pointers. Simple for today's dynamic languages. I forgot the details; I think it might have been CSG intersection and union objects.
http://www.povray.org/
An interesting bit of history. Cfront, the original C++ implementation output C code and then requires a C compiler to actually build the final code. So, anything that could be expressed in C++ could be written as C.
One way to handle inheritance is by having nested structs:
struct base
{
...
};
void method_of_base(base *b, ...);
struct child
{
struct base base_elements;
...
};
You can then do calls like this:
struct child c;
method_of_base(&c.b, ...);
You might want to look at Objective-C, that's pretty much what it does. It's just a front-end that compiles Objective-C OO code to C.