0

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?

Community
  • 1
  • 1
infect
  • 41
  • 1
  • 8

8 Answers8

8

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).

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • Yes. But this was one of the questions in my test and i need to convert it in C using whatever construct I wish to. – infect Oct 23 '12 at 13:55
  • a static function in c can only be called within that particular c file. so, kinda like a private if you treat this c file as a class scope. – user1500049 Oct 23 '12 at 14:06
  • Yes, file-scope is one way of scoping, the other is library scoping, where the function is not exported, so those using the library won't be able to see or call the method. This is what I meant by implementing a kind of friendship. – CashCow Oct 23 '12 at 14:35
4

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();
...
Lundin
  • 195,001
  • 40
  • 254
  • 396
1

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 */ }
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • -1 for the incorrect statement about no access control in C. See the link I posted to see how private encapsulation is achieved in C. – Lundin Oct 23 '12 at 14:00
  • @Lundin: That's not access control, and it's not a language feature. It's just a programming technique. By the same token you could say that "C has TCP/IP", just because it's possible to write a TCP/IP library in C. Or polymorphism or inheritance for that matter. You can always *achieve the effect* (because you can do anything in C), but it's not a native language feature. – Kerrek SB Oct 23 '12 at 14:04
  • 1
    @Lundin - Where in that post do you have "private" data? – Mike Oct 23 '12 at 14:07
  • @KerrekSB You are not correct, incomplete type is a language feature of C. See C11 6.7.2.3. – Lundin Oct 23 '12 at 14:25
  • @Mike Updated. The struct in the C file has an implementation that is not visible or accessible by the caller. The concept is known as opaque/incomplete type. – Lundin Oct 23 '12 at 14:29
  • @Lundin: Incomplete types also exist in C++. But C++ has access control on top of that. – Kerrek SB Oct 23 '12 at 14:32
  • @KerrekSB Yes, C++ achieves private encapsulation in less ugly ways. But that doesn't mean that you cannot achieve it in C, through the language feature known as incomplete type. – Lundin Oct 23 '12 at 14:36
1

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.

Scott Wales
  • 11,336
  • 5
  • 33
  • 30
0

In a struct, you can write pointers on functions to simulate C++ class...

Kharec
  • 58
  • 5
  • And then you will have to assign each function pointer to an instance every time – SwiftMango Oct 23 '12 at 13:56
  • You don't need any pointer in the "class" instance. Don't add any pointer to the struct unless you want to simulate virtual functions. And even in this case you have no pointer to functions in the struct but a pointer to a function table. – harper Oct 23 '12 at 13:57
0

Classes are a C++ concept, not a C concept. However, you can implement some OO design features in C through the use of pointers and PIMPL.

Here is how I would implement a class in C:

A.h

   struct privateA;
   struct A {
     struct A_private* private;
     int c,d;
   };
   extern void A_func1(struct A*);
   extern struct A* A_new();

A.c

   struct A_private {
     int a,b;
     int e,f;
   };

   static struct A_private* A_private_new() {
     struct A_private_new* this = malloc(sizeof(struct A_private);
     this->a = 0;
     this->b = 0;
     this->e = 0;
     this->f = 0;
   }

   struct A* A_new() {
     struct A* this = malloc(sizeof (struct A));
     this->private = A_private_new();
     this->c = 0;
     this->d = 0;
   }

   void A_func1(struct A* this) { this->c = 12; }
   static void A_fun(struct A* this) { this->d = 7; }  

main.c:

#include "A.h"
int main () {
  struct A* a = A_new();
  A_func1(a);
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • There is not really any reason in C nor C++ to have public member variables though, as everything should be accessed through setters/getters in a pure OO design. If you drop the public member variables, you can drop the whole struct declaration in the header file, and the code will become easier to understand and maintain. – Lundin Oct 23 '12 at 14:23
0

There are well-known ways to achieve most of this in C, even without language support. The one thing you can't do manually is distinguishing between private and protected.

/* Foo.h */
struct Foo {
    int c, d;
};

struct Foo* newFoo(); /* you can't create these on the stack */
void Foo_func1(struct Foo*);

The trick is just to hide the things callers shouldn't have access to. Unlike using a fully opaque type, we can choose to expose public members directly without requiring a function call.

/* Foo.c */
struct Foo_private {
    struct Foo pub;
    int a, b;
    int e, f; /* note I'm not distinguishing private */
};

struct Foo* newFoo()
{
    struct Foo_private *f = malloc(sizeof(*f))
    /* initialize */
    return &f->pub;
}

struct Foo_private* cast(Foo *f)
{
    /* can do cunning things with offsets for inheritance,
       but this is the easy case */
    return (Foo_private *)f;
}

void Foo_func1(Foo *f)
{
    struct Foo_private *fp = cast(f);
    /* access private members here */
}
Useless
  • 64,155
  • 6
  • 88
  • 132
  • There is not really any reason in a pure OO design to have public member variables though. It doesn't make sense in C++ either. – Lundin Oct 23 '12 at 14:34
  • Who said anything about pure OO design? OP's question has public members, I gave public members. – Useless Oct 23 '12 at 14:35
  • Yes, I know, I'm just pointing out that the original question was flawed to begin with. – Lundin Oct 23 '12 at 14:37
  • @Lundin but you could need public function pointers to implement virtual functions or abstract classes/interfaces. – p91paul May 27 '21 at 23:28
0

There are no class in C but by using struct and functions you can do basic process without inheritance and polymorphism.

Polymorphism
  • 249
  • 1
  • 9