how to implement a class in c [duplicate]

Possible Duplicate:
How do you implement a class in C?

In my test, I am told I need to find a way to implement the following class in C

class A
{
    private:
      int a,b;
    public:
      void func1();
      int c,d;
    protected:
      int e,f;
      void fun();
};

Also does C compiler support the access specifiers private, public and protected inside structures?


Solution 1:

There are no classes in C, only structs. There are classes in C++.

There is also no private:

struct A
{
   int a, b;
   int c, d;
   int e, f;
};

void func1( struct A* );

void fun( struct A* );

But everything is public.

In order to make things more encapsulated, you would hide the actual implementation detail of struct A and show just a forward declaration with the public methods.

protected makes no real sense as there is no inheritance. You can sort-of implement "friendship" by exposing your detail or its functionality to certain internal modules but friendship is not the same as protected, which simply can't exist within C.

In your class you have made two of the members public but if we "hide" struct A we hide everything, so provide getters and setters instead.

Alternatively we can "hide" part of our struct, something like: struct A1;

struct A
{
   struct A1 * privatePart;
   int b, c;  // public part     
};

although it gets "messy" as you have to start allocating the private part (and remember in C there are no smart pointers or destructors so you'll have to be a lot more careful with memory management).

What a lot of C APIs use for this is a naming convention whereby they call "private" variables "reserved", often reserved1, reserved2 etc. The compiler won't stop you writing to them, but you obviously do so at your own risk, and the intention is clear that you are not supposed to access these members (other than direct copying or similar).

Solution 2:

This is how you do private encapsulation in C. The concept is known as opaque type, or more formally, incomplete type.

myclass.h

typedef struct myclass myclass;


myclass* myclass_construct (void);

void     myclass_set_x (myclass* this, int x);
int      myclass_get_x (const myclass* this);

void     myclass_destruct (myclass* this);

myclass.c

#include "myclass.h"

struct myclass
{
    int x; // this is a private variable
};


myclass* myclass_construct (void)
{
    myclass* instance = malloc (sizeof(myclass));

    if(instance == NULL) { /* error handling */ }

    instance->x = 0;

    return instance; 
}

void myclass_set_x (myclass* this, int x)
{
    this->x = x;
}

int myclass_get_x (const myclass* this)
{
    return this->x;
}

void myclass_destruct (myclass* this)
{
    free(this);
}

static myclass_private_member (something_t s)
{
    // pure private function, do something internal here
}

main.c

#include "myclass.h"

myclass* mc = myclass_construct();
...

Solution 3:

There is no access control in C. Otherwise, you can approximate some of the functionality of C++ class member functions via free functions:

struct A { int a, b, c, d, e, f; };

void A_func1(struct A * th) { /* use "th->a" etc. */ }
void A_fun(struct A * th) { /* ditto */ }

Usage:

struct A a;

A_func1(&a);
A_fun(&a);

As @CashCow says, you can get a decent amount of separation of implementation and interface by structuring your translation units properly. For example:

mylib.h: (ship this)

struct A;
void A_func1(struct A *);

mylib_secret_impl.c: (only ship the binary!)

#include "mylib.h"

struct A { int a, b, c, d, e, f; };

void A_fun(struct A * th) { /* ... */ }
void A_func1(struct A * th) { /* use A_fun(th) and members of *th */ }

Solution 4:

C doesn't support access specifiers, however you can emulate some of their functionality using anonymous structs that are only defined in an implementation file.

// foo.h
typedef struct Foo Foo;
Foo * FooAlloc(int bar);
void  FooFree(Foo *);

// foo.c
struct Foo {
    int bar;
};
Foo * FooAlloc(int bar){
    Foo * f = malloc(sizeof(*f));
    f->bar = bar;
    return f;
}
void FooFree(Foo * f){free(f);}

The bar member of struct Foo can only be accessed by functions in foo.c. The disadvantage is you can't create a Foo on the stack. Similarly you could put the definition into a separate 'foo_private.h' header to emulate protected access.