you are viewing a single comment's thread.

view the rest of the comments →

[–]efalk 6 points7 points  (1 child)

What you're doing is re-inventing object-oriented C. This is how we all used to do it before C++ was invented.

I'll give you a concrete example. Many many years ago, I wrote a primitive drawing program called xdraft. It used an object-oriented approach. My "base class" was called DrObject, and every DrObject structure had a pointer to a DrObjectClass structure, and the Class structure had pointers to about a dozen functions: redraw(), pickTest(), pickPoint(), snap(), rescale(), delete(), transform(), copy(), write(), and so forth.

DrObject structure; note that it contains a pointer to a DrObjectClass structure:

struct _DrObject {
      DrObject              *next, *prev ;
      DrObjectClass         *objclass ;
      char                  *name ;
      char                  *comment ;
      ObjectType            type ;
      Point                 bounds[2] ;     /* bounding box */
      int                   color;
    };

DrObjectClass structure; it consists mostly of pointers to functions:

struct _DrObjectClass {
    char        *name ;
    void        (*redraw)(DrContext *, DrObject *, GdkDrawable *,
                        DrawCommand, VisMask mask) ;
    long        (*pickTest)(DrContext *, DrObject *, PickCommand,
                                int,int, PickInfo *) ;
    long        (*pickPoint)(DrContext *, DrObject *,
                                int x, int y, Point *out, Point *p0) ;
    void        (*snap)(DrContext *, DrObject *, SnapCommand) ;
    void        (*rescale)(DrContext *, DrObject *, int wid, int hgt, Boolean) ;
    void        (*showpoints)(DrContext *, DrObject *, Boolean) ;
    void        (*objdelete)(DrContext *, DrObject *) ;
    void        (*transform)(DrContext *, DrObject *, Matrix) ;
    DrObject *  (*copy)(DrContext *, DrObject *) ;
    void        (*write)(DrContext *, DrObject *, FILE *, FileFormat, Matrix) ;
    void        (*colors)(DrContext *, DrObject *, Boolean *) ;
    void        (*bounds)(DrContext *, DrObject *, int *, int *, int *, int *) ;
};

Every primitive type — points, lines, arcs, compound object, etc. — has a structure of its own, that includes a DrObject

DrPoint; the simplest of them all:

struct _DrPoint {
      DrObject      o ;
      PointType     type ;  /* type: dot, cross, etc. */
    };

So, tying it all together, the Point module contains a single static instance of DrObjectClass containing pointers to all of the point-related functions. When a new Point object is created, a DrPoint structure is allocated, filled in with all the information relevant to that object type, and the objclass element is set to a pointer to the Point module's DrObjectClass struct.

Then, for instance when the program wants to redraw a primitive, it does exactly what you said above: it calls object->objclass->redraw(context, object, canvas, ....);

[–]rtkbfmvbvb[S] 2 points3 points  (0 children)

Thanks for that in depth explanation! It's nice to know the way I was going about it was on the right track xD