axis-c-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Samisa Abeysinghe (JIRA)" <>
Subject [jira] Created: (AXIS2C-255) Improvements to inheritance model
Date Wed, 06 Sep 2006 09:37:22 GMT
Improvements to inheritance model

                 Key: AXIS2C-255
             Project: Axis2-C
          Issue Type: Improvement
    Affects Versions: Current (Nightly)
            Reporter: Samisa Abeysinghe

In Axiom and a few others places, we have a relationship between types
which in Java is inheritance.  For example, element and
processing_instruction both inherit from node.  However, in C there is
no inheritance relationship. Instead there are two distinct objects.
For example, instead of having an element which *is a* node, for each
element object there is a separate node object and the node object
points to the element object.  This is confusing and inefficient. This
is essentially doubling the number of allocations and adding an extra
layer of indirection.

It is a little bit tricky to do OO inheritance in straight C (there's a
reason why people use C++...), but it is doable.  Here's some sample

/* a.h */

struct a;

struct a_ops {
  void (*destroy)(struct a *);
  void (*x)(struct a *);

struct a {
  const struct a_ops *ops;

#define A_DESTROY(pa) ((pa)->ops->destroy(pa))
#define A_X(pa) ((pa)->ops->x(pa))

/* b.h */

struct b;

struct b_ops {
  struct a_ops base;
  void (*y)(struct b *);

struct b {
  const struct b_ops *ops;

/* cast a struct pb * to a struct pa * */

#ifdef __GNUC__
/* use an inline where available for proper type-checking */
inline struct a *B_BASE(struct b *pb)
  return (struct a *)pb;
#define B_BASE(pb) ((struct a *)(pb))

#define B_DESTROY(pb) A_DESTROY(B_BASE(pb))
#define B_X(pb) A_X(B_BASE(pb))
#define B_Y(pb) ((pb)->ops->y(pb))

/* a.c */

struct a_impl {
  struct a iface;
  int m;

/* note that if the class can be inherited from, these really need to be
non-static and declared in a header file */

void a_destroy(struct a *a);
void a_x(struct a *a);  

static const struct a_ops a_ops = {

void a_init(struct a_impl *a)
  a->m = 17;

struct a *create_a()
  struct a_impl *a = malloc(sizeof(struct a_impl));
  a->iface.ops = &a_ops;
  /* factor out initialization into function so it can be called
     by superclasses */
  return &a->iface;

void a_destroy(struct a *a)

void a_x(struct a *a)
  ((struct a_impl *)a)->m = 42;

/* b.c */

struct b_impl {
  struct a_impl base;
  int n;

void b_destroy(struct a *);
void b_x(struct a *);
void b_y(struct b *);

static const struct b_ops b_ops = {

void b_init(struct b_impl *b)
  b->n = 57;

struct b *create_b()
  struct b_impl *b = malloc(sizeof(struct b_impl));
  b->base.iface.ops = &b_ops.base;
  /* note we have to cast here, unlike in the no inheritance case */
  return (struct b *)b;

void b_destroy(struct a *a)
  /* clean up our stuff first */
  /* then call base destructor */

void b_x(struct a *a)
  struct b_impl *impl = (struct b_impl *)a;
  /* for example */
  impl->base.m = 42;
  impl->n = 43;

void b_y(struct b *b)

/* foo.c */

void foo()
  struct a *a;
  struct b *b;

  b = create_b();
  a = create_a();
  b = create_b();
  a = B_BASE(b);

(based on comments by James)

This message is automatically generated by JIRA.
If you think it was sent incorrectly contact one of the administrators:
For more information on JIRA, see:


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message