How could one implement C++ virtual functions in C

12,390

Solution 1

Stolen from here.

From the C++ class

class A {
protected:
    int a;
public:
    A() {a = 10;}
    virtual void update() {a++;}
    int access() {update(); return a;}
};

a C code fragment can be derived. The three C++ member functions of class A are rewritten using out-of-line (standalone) code and collected by address into a struct named A_functable. The data members of A and combined with the function table into a C struct named A.

struct A;

typedef struct {
    void (*A)(struct A*);
    void (*update)(struct A*);
    int (*access)(struct A*);
} A_functable;

typedef struct A{
    int a;
    A_functable *vmt;
} A;

void A_A(A *this);
void A_update(A* this);
int A_access(A* this);

A_functable A_vmt = {A_A, A_update, A_access};

void A_A(A *this) {this->vmt = &A_vmt; this->a = 10;}
void A_update(A* this) {this->a++;}
int A_access(A* this) {this->vmt->update(this); return this->a;}

/*
class B: public A {
public:
    void update() {a--;}
};
*/

struct B;

typedef struct {
    void (*B)(struct B*);
    void (*update)(struct B*);
    int (*access)(struct A*);
} B_functable;

typedef struct B {
    A inherited;
} B;

void B_B(B *this);
void B_update(B* this);

B_functable B_vmt = {B_B, B_update, A_access};

void B_B(B *this) {A_A(this); this->inherited.vmt = &B_vmt; }
void B_update(B* this) {this->inherited.a--;}
int B_access(B* this) {this->inherited.vmt->update(this); return this->inherited.a;}

int main() {
    A x;
    B y;
    A_A(&x);
    B_B(&y);
    printf("%d\n", x.vmt->access(&x));
    printf("%d\n", y.inherited.vmt->access(&y));
}

More elaborate than necessary, but it gets the point across.

Solution 2

@GCC....A virtual function is declared in the Base class of an object and is then "overriden" or implemented in the sub classes. i.e., say you have Vehicle Base class and you create two sub-classes, Motorcycle and, Automobile. The Base class would declare a virtual function of AddTires() Then the Sub Classes would implement this function and each sub class would implement it differently. A car has 4 wheels, where a motorcycle has 2. I can't give you the syntax for C or C++, though. Hope this helps

Share:
12,390
Admin
Author by

Admin

Updated on June 06, 2022

Comments

  • Admin
    Admin about 2 years

    The C++ language provides virtual functions. Within the constraints of a pure C language implementation, how can a similar effect be achieved?

  • Ramadheer Singh
    Ramadheer Singh about 14 years
    actually, there is a notion of inheritance in C but it does not respect ACCESS control here : stackoverflow.com/questions/577465/…
  • MikeTWebb
    MikeTWebb about 14 years
    Of course, my answer is based on C# and that object model
  • Alerty
    Alerty about 14 years
    @Gollum: A C++ struct is not like C struct.
  • ManniAT
    ManniAT about 14 years
    You can't do it directly (class is missing :)) - but it's no problem to implement such a system using structures and function pointers.
  • RBerteig
    RBerteig about 14 years
    Note that it is (usually) possible to interoperate with C++ virtual functions from C, if enough is known about the C++ ABI. For example, Windows COM uses virtual functions to declare interfaces, and there is a technique (made just barely usable by a lot of macros) for declaring COM interfaces and calling through them from C. Also, C++ started life (with many of its current features including virtual functions) as a preprocessor that read C++ text and wrote C. So it is possible to implement them in C, just not pleasant.
  • jer
    jer about 14 years
    That question is on C++ which has inheritance. All you can do in C is simulate it by storing pointers to your functions on the structures you're passing around.
  • Admin
    Admin about 14 years
    he said when we implement phyton in c we use some way ;'if you use same way ,you will achieve'
  • Tim Schaeffer
    Tim Schaeffer about 14 years
    @RBerteig: but, of course, there is no standard C++ ABI, so any C code which gets cozy with C++ virt funcs will be unportable. So if you want a portable, dynamically-linkable virtual function interface (like COM), you have to at least act like you're using C.
  • Ramadheer Singh
    Ramadheer Singh about 14 years
    @Alerty, really ? I did not know that can you elaborate?
  • RBerteig
    RBerteig about 14 years
    @Tim, true. And COM was defined in a way that "coincidentally" allowed an Interface to be represented as an array of pointers to functions in C and as a virtual function table in Visual C++. This was acceptable because portability was not a priority for Microsoft. But remains an example of one way that virtual functions can be implemented in and called from C.
  • stinky472
    stinky472 about 14 years
    +1 Great example: this is about as close as you can get to translating vtables to C and is far more elegant than C programmers doing things like function pointer casts or casting structures of function pointers. It's still bulky and awkward, but hey, C wasn't designed for this.
  • Alerty
    Alerty about 14 years
    @Gollum: It is possible in C to have functions in structs. One has to use a function pointer and set it (this would be rather ugly). Also, please note that there is no public/private/protected keyword in C. In C++, a struct is the same as a class except that everything is public by default.
  • Alerty
    Alerty about 14 years
    @stinky472: I agree with you, but when someone is at the point of needing code like this it just makes no sense. Certain languages are better suited for certain problems.
  • stinky472
    stinky472 about 14 years
    Very true, but I have been forced to work in C systems trying to implement OOP. They did it by casting structures with function pointers (like casting struct A), rather than just passing A for polymorphism and allowing every subclass-like struct to simply store A and assign appropriate function addresses and data to it. This, at least, is far more elegant than struct casting or casting function pointers.
  • Bandicoot
    Bandicoot about 12 years
    I don't think A::access() is present in the virtual table as this is a non-virt function.
  • Ziezi
    Ziezi about 7 years
    Just a note: the link in the beginning is broken.
  • Ziezi
    Ziezi about 7 years
    In void B_B (B* this) you are passing a pointer of type B* to a function with argument of type A*, and assigning B_functable, B_vmt to A_functable, this->inherited.vmt, without expicit casting nor error, how's that possible? (i.e it is not possible: it gets underlined as an error even before compilation).