polymorphism in C

J

Jack

I found a code to do polymorphism in C (taken from a book):

struct Class {
size_t size;
void * (* ctor) (void * self, va_list * app);
void * (* dtor) (void * self);
void * (* clone) (const void * self);
int (* differ) (const void * self, const void * b);
};

The book says the first argument of those functions of the above struct has to be a pointer to "self". Why?

Thanks.

Jack
 
E

Eric Sosman

I found a code to do polymorphism in C (taken from a book):

struct Class {
size_t size;
void * (* ctor) (void * self, va_list * app);
void * (* dtor) (void * self);
void * (* clone) (const void * self);
int (* differ) (const void * self, const void * b);
};

The book says the first argument of those functions of the above struct has to be a pointer to "self". Why?

If the function -- (*differ)(), say -- wants to operate on the
struct instance, it needs a way to find that struct.

If that's not clear, try implementing an augmented class:

struct Class {
size_t size;
...
void (*print)(FILE *stream); // no "self"
};

Your mission, should you choose to accept it, is to write a
function that `print' could reasonably point to. Note that
this function has no obvious way to discover which struct it
is supposed to print ...
 
J

JimB

Eric said:
If the function -- (*differ)(), say -- wants to operate on the
struct instance, it needs a way to find that struct.

If that's not clear, try implementing an augmented class:

struct Class {
size_t size;
...
void (*print)(FILE *stream); // no "self"
};

Your mission, should you choose to accept it, is to write a
function that `print' could reasonably point to. Note that
this function has no obvious way to discover which struct it
is supposed to print ...

Your imposition, should you choose to acknowledge it... well it is (was? are
we all grown up now Mz. "court-appointed" "psychologist"? That means ...
what does it mean? Am I "crazy"? No, THEY need more than that (can you say
gestapo?). What about the gun? Will I accept it as my savior and bow to it?
The record shows that I am "a flag-burner".

I feel this is an M.O.: all horrors that preceded this time.

Rape is rape. Fear is a valid reason not to "die for your country". Their is
no "country". There is rape though. Enlist the immature (yes, you lil bitch
wannabe authoritarian of deciding peoples's fate: **** you bitch), in the
name of "Freedom!", of course. Rape is rape.

Rape is "easy". No one dies, there is no war. Is war easier than rape? I
say, "you" are "the president of the united fucking states", say, and what
do you say to christians on their holiday? Pfft! Hello: their sufferring is
a bit less than donald trump and bill gates but you will come to your
salvation.. when you DIE [for your country].

For the stupid: there is no "country". There is no "nation". There is no
FLAG.. You though, at every juncture, from birth on, are charged with
"carrying the flag".

Rape is rape.

a big problem.
 
S

Shao Miller

a big problem.

The regulars will most probably never forgive me, but...

What is it that compels you to type this (above) and the "Why Jacob
Navia hates C" post? I believe that you recognize what you've typed as
being off-topic for people interested in the C programming language. So
if that's true, why post these? Because you can? Do you gain
something? Are you drunk? Are you bored? Are you hopeful that a
reader will have some poetic appreciation of these? Do you just want
some feedback, like mine? What sorts of comments could you throw my
way? Are you a fledgling artificial intelligence with limited means of
interacting with the world? Is there something you desire that one or
more comp.lang.c readers could grant you?

I'm trying to understand your motives. You presumably sit down at your
computer and open up your news-reader, then fetch the latest comp.lang.c
material, then read at least some of the postings, then... What? You
think. You decide to post something. Why? Perhaps you carefully
choose what type. If so, what sorts of thoughts go into those choices?

Do you ever consider anyone else's perspective? What would it be like
to be someone else, reading a post like one of these two that you've
typed? How might other people feel about them? How might other people
react? Is there a particular way that you want other people to react?
Do you take comfort in the knowledge that someone has read what you've
typed (like this)? Do you enjoy observing a certain amount of output
from yourself result in a larger response from another (like this)?

What is driving you? Can you be honest about it in a response? Or is
the answer private? Is there a sequence of magic words that could
result in your cessation of posting off-topic messages? How about
this?: Please stop posting off-topic messages.
 
J

JimB

Shao said:
The regulars will most probably never forgive me, but...

What is it that compels you to type this (above) and the "Why Jacob
Navia hates C" post? I believe that you recognize what you've typed
as being off-topic for people interested in the C programming
language. So if that's true, why post these? Because you can?


That is a valid quetioon (not that other questiins are not valid)
Do
you gain something?

wouldn't it be that I am missing someone?
Are you drunk? Yeah.
Are you bored?
Wasn't the drunken thiing the prob?
Are you hopeful
that a reader will have some poetic appreciation of these?
No I am not gifted with music (I just get to listen to it and hate
you))
just want some feedback, like mine? What sorts of comments could you
throw my way? Are you a fledgling artificial intelligence with
limited means of interacting with the world?

Yes..For sure.
Is there something you
desire that one or more comp.lang.c readers could grant you?

No. I''m way ok, and if you wanna go a few rounds with me well, I wil
**** you up.]]

Don't call me out in defense of your .......... I jest, I don't , I mean I
hateL USA go to hell.
 
S

Shao Miller

No. I''m way ok, and if you wanna go a few rounds with me well, I wil
**** you up.]]

Sometimes I don't bother trying to be unpredictable, either. ;)

Yes you are right on pint.
what is you point?

I might have two points, though neither of them would be particularly
attractive or repulsive:

1. I don't understand your motives for posting off-topic messages, but I
might like to.

2. I'd enjoy comp.lang.c more without such off-topic messages.

Good fortune to you.
 
K

Keith Thompson

Shao Miller said:
The regulars will most probably never forgive me, but...

What is it that compels you to type this (above) and the "Why Jacob
Navia hates C" post?
[snip]

Shao, by all means feel free to waste your time asking about the
motivations of an obvious troll. But please don't waste everyone
else's time by doing it here.

(JimB: *plonk*)
 
S

Shao Miller

Shao Miller said:
The regulars will most probably never forgive me, but...

What is it that compels you to type this (above) and the "Why Jacob
Navia hates C" post?
[snip]

Shao, by all means feel free to waste your time asking about the
motivations of an obvious troll. But please don't waste everyone
else's time by doing it here.

That is why the subject clearly includes "off-topic" in it.

If you can provide me with the e-mail address for this poster, I will
gladly continue it off-list. But to be honest, if you feel so strongly
about it, I'm happy to drop it, as your posts are more enjoyable and
topical.

- Shao Miller
 
M

Mark Storkamp

Shao Miller said:
Shao Miller said:
On 12/16/2012 02:40, JimB wrote:

a big problem.


The regulars will most probably never forgive me, but...

What is it that compels you to type this (above) and the "Why Jacob
Navia hates C" post?
[snip]

Shao, by all means feel free to waste your time asking about the
motivations of an obvious troll. But please don't waste everyone
else's time by doing it here.

That is why the subject clearly includes "off-topic" in it.

If you can provide me with the e-mail address for this poster, I will
gladly continue it off-list. But to be honest, if you feel so strongly
about it, I'm happy to drop it, as your posts are more enjoyable and
topical.

- Shao Miller

You're delusional if you think you'll accomplish anything keeping it
on-list.

*plonk*
 
S

Shao Miller

You're delusional if you think you'll accomplish anything keeping it
on-list.

*plonk*

Mission accomplished. But seriously, it doesn't take much for some
people, does it? Enjoy your plonk.
 
J

Jack

If the function -- (*differ)(), say -- wants to operate on the

struct instance, it needs a way to find that struct.

The function (*differ)() is a member of the the struct Class. So it operates on Class's instance, right? For example:

Class *myclass = (Class*)malloc(sizeof(Class));
myclass->differ();


Thanks.

Jack
 
K

Keith Thompson

Jack said:
The function (*differ)() is a member of the the struct Class. So it
operates on Class's instance, right? For example:

Class *myclass = (Class*)malloc(sizeof(Class));

The cast is unnecessary and potentially dangerous. The above is better
written as:

Class *myclass = malloc(sizeof *myclass);
myclass->differ();

No, it doesn't *implicitly* operate on the instance.

The *function* isn't a member of the struct. The struct has a
member named `differ` that's a *pointer* to some function. For a
given object of type `struct Class`, there has to be code that
assigns a pointer to some function to the `differ` member -- and
there has to be a definition of that function. And that function
definition is not directly associated with the type `struct Class`.

C does not have member functions. The code above is a way of
*emulating* member functions using the features that C does have.

In C++, non-static member functions take an implicit first argument
that's a pointer to the current object; the pointer can be referred
to inside the function as `this`. C has no such mechanism, which
is why it all has to be done explicitly. (And it can be argued
that if you're doing this kind of thing, you should probably use
a language that has better support for it, whether that's C++
or some other OO language.)
 
I

Ian Collins

Please wrap your lines and clean up the mess that awful google interface
makes of your replies!
The function (*differ)() is a member of the the struct Class. So it operates on Class's instance, right? For example:

Class *myclass = (Class*)malloc(sizeof(Class));

Loose the cast.
myclass->differ();

It would if you called it with the correct parameters, one of which is
the instance.
 
S

Shao Miller

The function (*differ)() is a member of the the struct Class. So
it operates on Class's instance, right? For example:

Class *myclass = (Class*)malloc(sizeof(Class));
myclass->differ();

3 minor points:

1. Casting the result of a call to 'malloc' is discussed in the C FAQ's
question 7.7b: http://c-faq.com/malloc/mallocnocast.html

2. If possible, please try to use the idiom:

complete_obj_type * some_obj = malloc(sizeof *some_obj);

Because 'sizeof' is not a function, it is an operator, and because it's
more specific to say that you're allocating storage for 'some_obj',
rather than to say that you're allocating storage for the type of
'some_obj'.

3. It's a good idea to check the result of your 'malloc' call before
using the object. You can do this with an 'assert' for development, or
you can actually handle the case where there's insufficient memory and
fail gracefully.

So adjusting your example:

Class *myclass = malloc(sizeof *myclass);
if (!myclass) {
/* Code to fail gracefully */
}

It's also worth noting that you haven't yet set the 'myclass->differ'
function pointer to anything, so that pointer value is indeterminate
until you do so. And you need to pass arguments that satisfy the
pointed-to function's parameter expectations.

But I don't know if you'd want to use 'malloc' for such a thing. You
might use something like:

Class *myclass = NewClass(sizeof *myclass);
if (!myclass) {
/* Code to fail gracefully */
}

where 'NewClass' might be something like:

#include <stddef.h>
#include <assert.h>

void DefaultClass(Class * class) {
static const Class default_class = {
sizeof default_class,
default_ctor,
default_dtor,
default_clone,
default_differ,
};
assert(class);
*class = default_class;
}

Class * NewClass(size_t class_sz) {
Class * result;

if (class_sz < sizeof *result) {
assert(!"Insufficient class size");
return NULL;
}

result = malloc(class_sz);

if (result) {
DefaultClass(result);
result->size = class_sz;
}

return result;
}

(Where each of the default_* functions are actually defined somewhere.)
That way, when you produce a new 'Class', you immediately throw some
useful defaults into it. This is a suggestion for a bit of "protection"
against programming errors and does incur overhead, so it's certainly up
to you.

- Shao Miller
 
B

BartC

Jack said:
The function (*differ)() is a member of the the struct Class. So it
operates on Class's instance, right? For example:

Class *myclass = (Class*)malloc(sizeof(Class));
myclass->differ();

Try and write the function that 'differ' points to, then you might
understand some of the problems.

In a slightly different language, you might write something like:

Class myclass;
....
myclass.differ(x); // remember you had that extra parameter

which might get translated behind the scenes to:

Class_differ(&myclass, x);

This has to be emulated in C, but it still boils down to having to call a
'differ' function specific for this class, with a pointer to the myclass
instance (the 'self' param) and any extra parameters that have been
specified.

You also still have to supply the actual body of this function somewhere,
which you've neglected in your example. In the C, this means initialising
that pointer to an actual function.

(And that sample class seems inefficient to me: having to store details of
all four functions - and perhaps a lot more - in every single instance of
the class. Which also need initialising for each instance. I'm sure that
information - the list of functions - only needs to exist in one place.
Although as written, it makes the call syntax simpler in C.)
 
S

Shao Miller

(And that sample class seems inefficient to me: having to store details of
all four functions - and perhaps a lot more - in every single instance of
the class. Which also need initialising for each instance. I'm sure that
information - the list of functions - only needs to exist in one place.
Although as written, it makes the call syntax simpler in C.)

I would not expect that the constructs that were shared would be used in
"an object having a certain class," but only in the instances of a class
itself.

That is, 'myclass' seems indicative of "a new class" rather than "a new
myclass." I'd guess that "myobj" might have its first member as a
'Class *', thus saving most of the storage requirement you mention.

Obviously I could be wrong, as I've no idea which book this is inspired
by. I'd read a PDF (for this sort of thing in C) once where "class
objects" and "class instance objects" were distinct subjects, though.

- Shao Miller
 
J

James Kuyper

On 12/17/2012 02:27 AM, Keith Thompson wrote:
....
In C++, non-static member functions take an implicit first argument
that's a pointer to the current object; the pointer can be referred
to inside the function as `this`. C has no such mechanism, which
is why it all has to be done explicitly. (And it can be argued
that if you're doing this kind of thing, you should probably use
a language that has better support for it, whether that's C++
or some other OO language.)

I'm sure you know this, and it's implicit in what you've said, but for
Jack's sake I want to say this explicitly: the fact that non-static C++
member functions take an implicit extra parameter which points at the
instance they were invoked on is one example of the many different ways
that C++ provides better support than C for this style of programming.
 
B

BartC

In C++, non-static member functions take an implicit first argument
that's a pointer to the current object; the pointer can be referred
to inside the function as `this`. C has no such mechanism, which
is why it all has to be done explicitly. (And it can be argued
that if you're doing this kind of thing, you should probably use
a language that has better support for it, whether that's C++
or some other OO language.)

The subject is polymorphism. That needn't have anything to do with OO.

I don't think it needs to be done with 'classes' and 'instances' and
'member' functions either. This might be just one technique the OP is
investigating.

(I've used polymorphism in my language projects for many years (I've only
recently discovered there was a special word for it!) The latest one is
implemented (indirectly) in C. In any case, my languages are definitely not
OO, and use techniques very different from the OP's example.

C will be OK to do this stuff, although the resulting clunky code won't be
pretty compared with a language where it's all built-in.)
 
G

Greg Martin

The subject is polymorphism. That needn't have anything to do with OO.

I don't think it needs to be done with 'classes' and 'instances' and
'member' functions either. This might be just one technique the OP is
investigating.

(I've used polymorphism in my language projects for many years (I've
only recently discovered there was a special word for it!) The latest
one is implemented (indirectly) in C. In any case, my languages are
definitely not OO, and use techniques very different from the OP's example.

C will be OK to do this stuff, although the resulting clunky code won't
be pretty compared with a language where it's all built-in.)

There are many uses of the word polymorphism. I believe the OP is
referring to subtype polymorphism, judging by the example. It seems to
me more useful, not to mention safe, in languages that provide the tools
to support it.

// subtype polymorphism

#include <stdio.h>

const char* one () {
return "one";
}

const char* two () {
return "two";
}

struct Number {
const char* (*num) ();
};

struct One {
const char* (*num) ();
};

struct Two {
const char* (*num) ();
};

void print (struct Number* n) {
printf ("%s\n", n->num());
}

int main () {
struct One o = { one };
struct Two t = { two };


print ((struct Number*)&o);
print ((struct Number*)&t);

return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top