Virtual Functions in C

At first I had no idea because C is not an object oriented programming language and there is no such thing as inheritance, but having some experience with C and knowing how virtual functions work I was thinking that there must be a way to mimic the virtual function

Photo by Pietro Jeng

At first I had no idea because C is not an object oriented programming language and there is no such thing as inheritance, but having some experience with C and knowing how virtual functions work I was thinking that there must be a way to mimic the virtual function implementation by using C structs, then I started getting my hands dirty.

For those who are wondering what virtual functions are here is a short description: A virtual function is a function that can be overridden on another inheriting class in order to have a different implementation. Virtual functions use a virtual method table mechanism (or vtable for short) to support function binding on run-time, furthermore virtual table is a static array that has an entry for each virtual function and each entry is a function pointer that points to the most-derived function accessible from that class. How the most-derived function would be determined is that on run-time method’s address is fetched from the object dispatch table.

To learn more do a Google search.

With that said, let’s have a simple C++ implementation of virtual functions:

class ClassA
{
public:
    ClassA() {data = 10;}
    virtual void set()
    {
        std::cout << "ClassA is increasing" << std::endl;
        data++;
    }
    int get()
    {
        set();
        return data;
    }

protected:
    int data;

};

class ClassB : public ClassA
{
public:
    void set()
    {
        std::cout << "ClassB is decreasing" << std::endl;
        data--;
    }
};

What was done in the code snippet above is that we have a class named ClassA where it has two methods, get() and set(); method named get() is marked as virtual function using the C++ virtual keyword and then it was derived on ClassB and its implementation has changed. Integer data on ClassA is marked as protected in order to have access to it on the derived class.

If we initialize and call the corresponding classes and methods in a main function like the snippet below:

int main()
{
    ClassA classA;
    ClassB classB;

    std::cout << "ClassA value: " << classA.get() << std::endl;
    std::cout << "ClassB value: " << classB.get() << std::endl;

    return 0;
}

We get the following output:

ClassA is increasing
ClassA value: 11
ClassB is decreasing
ClassB value: 9

Now we jump to the C implementation of virtual function concept. Knowing that virtual functions are represented as function pointers in vtable and vtable is a static array, we need to create a struct that mimics the ClassA, a vtable for our ClassA that has function pointers and the ClassA function implementation, and those are represented in code below (read code comments also):

// forward declaration of our struct before it's definition
struct ClassA;

// The actual function table that holds function pointers.
typedef struct {
    void (*ClassA)(struct ClassA*); // the "constructor"
    void (*set)(struct ClassA*); // set function
    int (*get)(struct ClassA*); // get function
} ClassA_functiontable;

typedef struct ClassA {
    int data;
    ClassA_functiontable *vtable; // ClassA virtual method table
} ClassA;

// ClassA's function prototypes (forward declarations)
void ClassA_constructor(ClassA *this); 
void ClassA_set(ClassA *this);
int ClassA_get(ClassA *this);

// Static array of the function table struct that contains ClassA's functions. 
ClassA_functiontable ClassA_vtable = {ClassA_constructor, 
                                  ClassA_set,
                                  ClassA_get };

// Implementation of functions and the constructor.                               
void ClassA_constructor(ClassA *this) {
    this->vtable = &ClassA_vtable; 
    this->data = 10;
}

void ClassA_set(ClassA *this) {
    printf("ClassA is increasing\n");
    this->data++;
}

int ClassA_get(ClassA *this) {
    this->vtable->set(this);
    return this->data;
}

In C we don’t have the “this” pointer that points to itself, I have named the parameter as “this” to mimic it’s use in C++ (and also this is similar to what C++ is doing under the hood).

As we have seen in the above code snippet, implementation of ClassA_get() function on ClassA calls the set() function on our virtual method table struct, let’s see how the implementation is being done when introducing another class:

// forward declaration of our struct before it's definition
struct ClassB;

// Same as above, the actual function table that holds function pointers.
typedef struct {
    void (*ClassB)(struct ClassB*);
    void (*set)(struct ClassB*);
    void (*get)(struct ClassA*);
} ClassB_functiontable;

typedef struct ClassB {
    ClassA inherited_class;
} ClassB;

void ClassB_constructor(ClassB *this);
void ClassB_set(ClassB *this);
int ClassB_get(ClassB *this);

ClassB_functiontable ClassB_vtable = {ClassB_constructor, ClassB_set, ClassB_get};

void ClassB_constructor(ClassB *this) {
// A type cast from ClassB to ClassA pointer is needed
    ClassA_constructor((ClassA*)this);

// Type casting should be done for the virtual table struct as well
    this->inherited_class.vtable = (ClassA_functiontable*)&ClassB_vtable;
}

void ClassB_set(ClassB *this) {
    printf("ClassB decreasing\n");
    this->inherited_class.data--;
}

int ClassB_get(ClassB *this) {
    this->inherited_class.vtable->set((ClassA*)this);
    return this->inherited_class.data;
}

As we see here we call same set() function from ClassB’s implementation using the vtable that points to the set() function on ClassA_functiontable (vtable) struct and we use the same data integer via “inherited” class, ClassA.

This is our main function in C:

int main() {
    ClassA classA;
    ClassB classB;

    ClassA_constructor(&classA);
    ClassB_constructor(&classB);
    printf("ClassA value: %d\n", classA.vtable->get(&classA));

   // We need to access get() via the inherited "parent" class 
   // class which in C it's shown in verbose manner as the call below.
    printf("ClassB value: %d\n", 
               classB.inherited_class.vtable->get((struct ClassA*)&classB));
}

This is the console output:

ClassA is increasing
ClassA value: 11
ClassB decreasing
ClassB value: 9

Of course this trick does not appear as natural as in C++ or another object oriented programming language and I have never had to implement similar approach when I wrote C programs in the past, but it still helps understand a possible under the hood implementation of a virtual function feature, and of course this is how I understood it while doing a simple research on the subject.