
\documentclass[12pt]{article}
\usepackage[T2A,OT1]{fontenc}
\usepackage[default]{cantarell}
\usepackage[a4paper, top=20mm, bottom=20mm, left=20mm, right=20mm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[russian, english]{babel}
\usepackage{tabu}
\usepackage{hyperref}
\usepackage{parskip}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage{float}
\floatstyle{boxed}
\restylefloat{figure}
\usepackage{setspace}
\onehalfspacing
\author{Artyom Bologov}
\date{\today}
\title{Object-Oriented C: A Primer}
\makeatletter
\def\endenv{\expandafter\end\expandafter{\@currenvir}}
\makeatother
\begin{document}
\maketitle

C is a marvelous language in how it can be small, efficient,
\href{run:making-c-prettier}{pretty,}
\href{run:making-c-uglier}{and ugly,}
all at the same time.
But what it lacks (driving modern developers to despair) is Object-Oriented Programming (OOP) facilities.
Yes, there's C++, but one doesn't talk about C++ in good social circles.
Especially when it's possible to simulate classes, objects, and methods in C.
Yes, it'll look slightly irregular, but bear with me.

This post is structured around Object-Oriented Programming concepts.
Starting from the simplest ones and slowly increasing the difficulty level.
Be prepared: OOP is quite a fuzzy set of ideas.
I'll exploit this fuzziness as much as possible—to
stay within what people call OOP while not parting with C and its blessed ways.
As a spoiler: the resulting system will be a Generic-based Single Inheritance one.

Here's a problem domain we're going to model: animals.
There are animals (yes, a classic OOP example).
Many families and species of animals.
I have a lovely cat named Kalyam, so I'm mostly interested in Feline.

\begin{figure}[h!]
\includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{./assets/oop-c-primer-animals.svg}
\caption{Inheritance hierarchy of an arbitrary sample of animals I am familiar with}\end{figure}

I'm going to model just that part of biological hierarchy.
Hopefully, we'll have enough material to crash-test the approach I suggest.

\section*{Encapsulation} \label{encapsulation}

This one is easy.
In its simplest definition, encapsulation is putting things into their buckets (called classes).
Encapsulation might also mean hiding data inside classes, but see
\pageref{visibility}{visibility section}
for that instead.
Encapsulation might also mean belonging of behavior (methods) inside classes.
But that's debatable: some languages have a generic-oriented OOP where methods are freestanding entities.
If anything, methods belong to their generic functions there.
That's the approach I'll use.
C (since C11) has generic dispatch, so
why not use the feature that's already there?

Putting the generics talk aside for a second, let's encapsulate some data, shall we?
\begin{figure}[h!]\begin{verbatim}
struct animal {
        char *name;
        char *species;
};
\end{verbatim}\caption{Animal structure definition listing useful data about it}\end{figure}

That's it, we've got our parent class ready.
The data is contained within, so we've got encapsulation.
What we don't yet have are animal classes, orders, genera, species, etc.
So let's create an extinct animal that can forgive me my poor biology knowledge:
\begin{figure}[h!]\begin{verbatim}
struct animal oldie = {.name = "Oldie", .species = "Miacid"};
printf("This really old animal is %s of %s specien", oldie.name, oldie.species);
\end{verbatim}\caption{Animal use example}\end{figure}

In case you don't like this
\verb|struct| talk, you can always define a macro and a type alias (capitalized, to please the Java crowd):
\begin{figure}[h!]\begin{verbatim}
#define class struct
typedef class animal Animal;
\end{verbatim}\caption{OOP macro and type we are going to use later}\end{figure}

That's all there is to encapsulation, really.

\section*{Inheritance} \label{inheritance}

With encapsulation out of the way, enter inheritance.
A way for classes to depend on each other and share behaviors/data.

A trick I learned
\href{https://felipec.github.io/good-taste/parts/1.html}{(from the "Good Taste" series of posts)}
just a few days ago: embedding structures inside each other.
Putting one structure as the first member of another,
you're making the outer structure castable to the inner one,
sharing the behavior between the two:
\begin{figure}[h!]\begin{verbatim}
typedef class carnivoire {
        Animal parent;
} Carnivoire;
\end{verbatim}\caption{Carnivoire class definition}\end{figure}

Now we can cast any animal to \verb|(Animal *)| and invoke \verb|Animal| methods:
\begin{figure}[h!]\begin{verbatim}
Carnivoire sabre_tooth = {{.name = "Diego", .species = "Dinictis"}};
eats((Animal *)\&sabre_tooth);
\end{verbatim}\caption{Example of Carnivoire use}\end{figure}

No, wait our animals don't know how to eat yet!
Let's teach them—with polymorphism!

\section*{Polymorphism} \label{polymorphism}

There's a default behavior to animals: they eat (duh).
That's why the diagram above includes the
\verb|eats()| method: any animal class eats something.
However, there are all sorts of animals.
Some eat plants.
Some eat fungus.
Some eat other animals (huh, a recursion?)
Knowing that the creature is an animal, it's hard to tell what they eat.
Here's how we express it with code:
\begin{figure}[h!]\begin{verbatim}
void animal_eats (Animal *self)
{
        printf("%s eats ???n", self->name);
}

#define eats(animal)
_Generic((animal),
         default: animal_eats)
((animal))
\end{verbatim}\caption{Polymorphic eats() method implemented as a macro}\end{figure}

For now, our \verb|eats()| macro/generic only has one default method: \verb|animal_eat|.
But you can already see how one can extend it with just another line of type+method.
Let's actually do that:
\begin{figure}[h!]\begin{verbatim}
void carnivoire_eats (Carnivoire *self)
{
        printf("%s eats meat (a shame—it involves killing other animals)n", self->parent.name);
}

#define eats(animal)
_Generic((animal),
         Carnivoire *: carnivoire_eats,
         default: animal_eats)
((__VA_ARGS__))
\end{verbatim}\caption{Carnivore eats() method}\end{figure}

Only one more line in the generic, and we have carnivoire-specific behavior!
That's what polymorphism's promise is: specifying behavior given a type.
\begin{figure}[h!]\begin{verbatim}
eats(\&sabre_tooth); // Diego eats meat...
\end{verbatim}\caption{Using carnivoire-specific eats() method}\end{figure}

\section*{Visibility} \label{visibility}

Most OOP systems have private/public/protected differentiation.
I can easily cast it aside based on the fact that e.g. Python doesn't have visibility as a concept.
But I'll try to implement it anyway.

The trick is treating structures as opaque data.
I mean, the user of the code doesn't have to know the data layout of the structure.
They have to use it as a raw pointer, relying on \verb|extern|-ed functions anyway.
This is exploited by many codebases.
They tend to hide the pointer to the "private" version of the structure, nested inside the "public" one.
WebKitGTK does this:
\begin{figure}[h!]\begin{verbatim}
class WebKit2.WebViewBase : Gtk.Container
  implements Atk.ImplementorIface, Gtk.Buildable {
  priv: WebKitWebViewBasePrivate*
}
\end{verbatim}\caption{WebKit WebView private structure example}\end{figure}

Relying on this tradition, we can say that structures are private by default.
What's public is their getters and setters.
So why not define some getters and setters for our structures?
\begin{figure}[h!]\begin{verbatim}
char *animal_get_name (Animal *self)
{
        return self->name;
}
void animal_set_name (Animal *self, char *name)
{
        self->name = name;
}
\end{verbatim}\caption{Example getter/setter for animals}\end{figure}

This is pretty boring, so let's define a new class with private fields and methods:
\begin{figure}[h!]\begin{verbatim}
#define private
typedef class feline {
        Carnivoire parent;
        private bool claws_out;
} Feline;

// Don't have to define name getter/setter: animal has it already.
bool feline_get_claws_out (Feline *self)
{
        return self->claws_out;
}
void feline_protract_claws (Feline *self)
{
        self->claws_out = true;
}
void feline_retract_claws (Feline *self)
{
        self->claws_out = false;
}
\end{verbatim}\caption{Feline (cat-like) class with special behavior for claws}\end{figure}

Notice that we don't have a setter for
\verb|claws_out|—retract/protract methods handle modification.
An important OOP technique of hiding the actual data behind the behavior.

\section*{Using the OOP system} \label{using-oop}

The code so far was pretty simplistic, and there wasn't much OOP.
This section and example will finally put the system to the test.
Let's define cats (I've been waiting for this!) and their behaviors:
\begin{figure}[h!]\begin{verbatim}
typedef class cat {
        Feline parent;
} Cat;

void cat_purr (Cat *self)
{
        printf("%s purrs...n", animal_get_name(self));
        feline_retract_claws(self);
}
void cat_eats (Cat *self)
{
        printf("%s eats micen", animal_get_name(self));
}

#define eats(animal)
_Generic((animal),
         Carnivoire *: carnivoire_eats,
         Cat *: cat_eats,
         default: animal_eats)
((animal))
\end{verbatim}\caption{Cats and their methods}\end{figure}

Testing this system yields:
\begin{figure}[h!]\begin{verbatim}
// My little sweet boy
Cat Kalyam = {{{{.name = "Kalyam", .species = "Felis catus"}}, .claws_out = true}};

printf("%s's claws are %stractedn",
       animal_get_name(\&Kalyam),
       (feline_get_claws_out(\&Kalyam) ? "pro" : "re"));
// Kalyam's claws are protracted

eats(\&Kalyam);
// Kalyam eats mice

cat_purr(\&Kalyam);
printf("%s's claws are %stractedn",
       animal_get_name(\&Kalyam),
       (feline_get_claws_out(\&Kalyam) ? "pro" : "re"));
// Kalyam's claws are retracted
\end{verbatim}\caption{Actually using the system}\end{figure}

These nested curly brackets are not looking right, begging for constructor methods.
But this post is too long already, so let's leave it for later.
What's important: Encapsulation, Inheritance, Polymorphism, and Visibility are there.
C can do OOP.
And it's not that hard really—what this post covers is quite simple and easy to scale.

You can look at the final code (compiles with GCC and Clang, even if with heaps of warnings)
\href{assets/oop-c-primer-original.c}{in oop-c-primer-original.c.}
And the cleaned-up
(and slightly extended with bird-specific details
if you wanted to see a more involved inheritance hierarchy) code
\href{assets/oop-c-primer-cleanup.c}{in oop-c-primer-cleanup.c.}
I hope that you're convinced OOP is possible in C, for better or worse.
Thanks for accompanying me on this journey!

\section*{Acknowledgements} \label{acknowledgements}

I owe a thanks to

\begin{itemize}\item Vasily Gerasimov for our discussions on what is or isn't OOP.
\item  Alex Alejandre for being attentive to my language and curious about the idea of the post.
\item
\href{https://github.com/OUIsolutions/Articles/blob/main/post-modern-c/post-modern-c.md}{Post-Modern C style guile}
for making me even consider a possibility of OOP in C.
\item
\href{https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md}{The Extendible _Generic post from CC}
for all too late a realization of a better approach.
They did OOP better, let's agree on that.
\end{itemize}

\par\noindent\rule{\textwidth}{0.4pt}
Copyright 2022-2025 Artyom Bologov (aartaka).
Any and all opinions listed here are my own and not representative of my employers; future, past and present.

\end{document}
