4

I was reading a book about implementing OOP in C and found this code :

void delete (void * self)
{ 
    const struct Class ** cp = self;
    if (self && * cp && (* cp) -> dtor)
        self = (* cp) -> dtor(self);
    free(self);
}

I want to know why the author had created a double pointer rather than a single pointer like this

void delete (void * self)
{ 
    const struct Class * cp = self;
    if (self && cp && cp -> dtor)
        self = cp -> dtor(self);
    free(self);
}

Is there any difference ?

anatolyg
  • 26,506
  • 9
  • 60
  • 134
Ashish Negi
  • 5,193
  • 8
  • 51
  • 95
  • 3
    For that you probably have to go back in the book, to where the author discusses the design, because we can't possibly know about the intentions of the author. – Some programmer dude Aug 20 '12 at 10:19
  • 1
    Also, check how this `delete` function is called. If it's passed the address of a pointer (e.g. `&pointer`) then the second version will crash and burn. – Some programmer dude Aug 20 '12 at 10:20
  • @JoachimPileborg yes, it well crush, but you night as well pass `pointer` instead of `&pointer`. – elyashiv Aug 20 '12 at 10:40

3 Answers3

5

In the author's object system, each object struct contains as its first element a pointer to its class:

typedef struct Object1 {
    Class *myclass;
    int data;
} Object1;

typedef struct Object2 {
    Class *myclass;
    double data;
} Object2;

That means that by treating a void * pointer to any object as a Class ** pointer, the class pointer can be followed without knowing the actual type of the object. This is allowed by the standard, because:

6.7.2.1 Structure and union specifiers

15 [...] A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. [...]

So any pointer Object1 * or Object2 * etc. can be converted to a pointer to its first element i.e. Class ** (since the first element of either is of type Class *, a pointer to the first element is of type Class **). See In C, does a pointer to a structure always point to its first member? for more information.

This is a legal approach, but a little difficult to follow. An equivalent would be to write

typedef struct BaseObject {
    Class *myclass;
} BaseObject;

and require that each object struct contain a BaseObject instance as its first member; the delete function would then cast self to BaseObject * and write ((BaseObject *) self)->myclass->dtor:

void delete (void * self)
{ 
    BaseObject *base = self;
    if (self && base->myclass && base->myclass—>dtor)
        self = base->myclass->dtor(self);
    free(self);
}
Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Could you elaborate on the non protable sentence? In what regard is it not portable? OS? Compiler? – drahnr Aug 20 '12 at 10:27
  • Sorry, I'm incorrect; it is allowed. 6.7.2.1:15 *A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa.* – ecatmur Aug 20 '12 at 10:46
  • Just wondered if I was writing unportable code on daily basis for years ;) - without even knowing. – drahnr Aug 20 '12 at 10:47
  • In the delete example that you have given at the end, you are not using "base" but "self". Is it right ? – Ashish Negi Aug 20 '12 at 10:58
1

In this system each object contains a pointer to its class in the first field. Effectively, Class **c = self gets the class structure from the object instance.

perreal
  • 94,503
  • 21
  • 155
  • 181
0

Becuase of the struct design:

*(const struct Class **)p=class;

in there: http://humelab.googlecode.com/svn-history/r3/trunk/ooc/new.c

as seen in the

void * new(const void *_class,...)
{
 const struct Class *class=_class;
 void *p=calloc(1,class->size);
 assert(p);
 *(const struct Class **)p=class;  //<------look here!

 if(class->ctor)
 {
  va_list ap;
  va_start(ap,_class);
  p=class->ctor(p,&ap);
  va_end(ap);
 }
 return p;
}
huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97
  • why am i not being able to do it like: const struct Class **pt = (const struct Class **) p; *pt = clas; is it "const struct *" ? then why C allows it to be changed like this in a line? – Ashish Negi Aug 20 '12 at 10:45
  • Is this a good design ? Am i reading the right from right source ? – Ashish Negi Aug 20 '12 at 10:46