views:

115

answers:

4

Say you have:

struct c_struct {
   int value;
   /* other stuff */
   void (* dump)();
};

and you'd like to, at some point:

c_struct_obj->dump();

I assume there's no way you could instantiate a c_struct object such that its particular "dump" function knows its particular "value" the way C++ methods know member variables (via the implicit "this" I suppose)? I guess I know the answer already ("no"). If so, are there other ways of using C structs in an OOPy way?

+6  A: 

Sure, you just have to pass this by yourself:

struct c_struct {
    int value;
    /* other stuff */
    void (* dump)(struct c_struct *this);
};

And then call it with:

c_struct_obj->dump(c_struct_obj);
Carl Norum
I feared it. I guess a global dump(c_struct_obj) is less typing.
carson921
@carson921, but then you lose the ability to have different `dump()` functions for each 'class' - polymorphism, so to speak.
Carl Norum
@Carl Norum oh, right. I'd need dump_cstruct() and dump_anotherstruct() etc. Thanks for pointing that out.
carson921
Actually, how would I implement the body of the dump function anywhere but in the global namespace?
carson921
@carson921, you can't - but when creating your objects, you can assign appropriate functions to each. Then the callers don't need to know what the type is, as long as they have `dump` at the same offset in the structure.
Carl Norum
@Carl Norum thanks. I just wrote a dump function that is static and specific to a compilation unit (file), so the caller has to access the dump function via the object, which is a little nicer. I don't think I've thought as far ahead (polymorphism etc) as you have on the topic.
carson921
A: 

You can use structs in this way but its a pain. All c++ member function get a *this pointer passed to them you can do the same but your dump functions will need to take the structure that its contained in as a parameter.

rerun
Oh well. Thanks for taking the time!
carson921
A: 

If you are using a C++ compiler, the only difference between a struct and a class is the default visibility of member variables (classes being private, structs being public). The this pointer is available within member functions.

struct test
{
    int x;

    void inc();
};

void test::inc()
{
    x++;
}

int main(void)
{
    test a;
    a.x = 1;
    a.inc();
    int b = a.x;

    return 0;
}

b == 2 here.

Mario
But he isn't, else he would just use a C++ member function. Which he isn't - he's using a function pointer.
DeadMG
A: 

You can do this and can even do inheritance. But the interfacing with it is a total mess and you get nowhere near, for example, the resource safety involved with C++'s deterministic automatic cleanup. Ultimately, you CAN do OOP in C, but it's just not worth the hassle compared to just using C++, as well as all the other features that C++ offers.

DeadMG
Thanks. I guess sometimes I just want some more OOP in C but if I go C++ I feel guilty not completely rethinking everything.
carson921
@carson921: Your program in C is probably still incredibly unsafe, regardless of the fact that you now get to notice it because you wrote some safe code.
DeadMG