[luau] C struct interdependency problem

Allens allens at bigisland.net
Sat Jun 22 21:05:01 PDT 2002


Hi all, I've been lurking a while...

Ray,

    As always one wonders... well what are you really trying to do... why
not use C++ for such a structure is what I wonder.  But if it's because you
prefer C or whichever.

Also I wonder why you want the syntax syle of

typedef struct Object Object... it's more common to create like this:

typedef struct Object_t
{
    Error superClass;
 } Object;

This is all in one step.  If you do it in two steps, it's still most common,
I think, to use:

struct Object_t
{
    Error superClass;
};

then subsequently the typedef is easier to read (at least for me):

typedef struct Object_t Object;

The thing is, the type being declared is an Object_t (the structs "tag" is
Object_t), and the new type is just "Object".

ObjectError
Object
Error
LinkedList/Stack (I'm assuming the stack.h file that has LinkedList means
that Stack is a LinkedList and it's a small typo)

The thing I'm looking at that might "not work out" is that you want Object
to have an Error member, and Error is a "subclass" of Object.  The
definition you show cannot compile because when you create an Object you
declare an Object (which has an Object (which has an Object (and so on)
member) member as a member, so it is being told to have declare an infinite
number of Objects to declare a single object.  You need to defer this
declaration with a pointer instead of a reference declaration so you can
create the member at runtime dynamically.

The place to make this indirection is the ObjectError member (the way you
have it set up).  So I have that as a pointer to ObjectError (ObjectError
*pError).  (see below).

When you create an Object like this
...

Object theinstance;
...

theinstance.pError will be an invalid value.  You will have to set it to
NULL like this

theinstance.pError = 0;  (or "=NULL;" if NULL is defined)

This is where C++ would come in handy because you could have a 'constructer'
that always cleared this value.

NOTE: this implies that you check for pError = 0, and use that to mean there
is no error.  If you don't want that, and you really want a member there,
then after the declaration of "theinstance" you have to follow right away
with.

theinstance.pError = malloc(sizeof (ObjectError));
memset(theinstance.pError, 0, sizeof(ObjectError));

Note to use C++ you can write C code that you simply augment with C++
constructions when useful, generally there is no cost performance or other
cost if just using C++ for the C++ version of subclassing.  The issue with
the pointer would be the same, but you would have the Object declared more
like this:

class Object
{
    ObjectError *pError;
    /* here you have a "constructor", which is called whenever an "Object"
is created */
    Object()
    {
        pError = 0; /* this ensures that pError is always 0, then you can
test for theinstance.pError == 0 to mean there is no error at the moment */
    };
};

Again, if you really don't want to check for the value equal to null (you
always want a real Error object as a member), then the constructor and class
declaration looks like this.

class Object
{
    ObjectError *pError;

    Object()
    {
        pError = new ObjectError();
    }

    ~Object()
    {
         /* this is the destructor, I'm putting this in because if you
create the error on construction, you should dispose of it when you throw
the object away */
        delete pError;
        pError = NULL;
    }
}

=======
this is the "see below" part! the C version of the answer
-----------

object.h
-----
#include "ObjectError";

typedef struct Object_t
{
    ObjectError *pError;
    ...
}
-----

objecterror.h
-----
#include "error.h"
typedef struct ObjectError_t
{
    Error    super_class;
} ObjectError;
-----

error.h
-----
#include "stack.h"

typedef struct Error_t
{
    Stack super_class;
} Error;
-----

stack.h
-----
typedef struct Stack_t
{
    Object    super_class;
} Stack;
-----

Hope this makes sense and is helpful.  It gets involved quick, feel free to
ask me to explain something I've said, I didn't want to go off on too many
tangents (I already added in C++!).

-craig



----- Original Message -----
From: "Ray Strode" <halfline at hawaii.rr.com>
To: <luau at videl.ics.hawaii.edu>
Sent: Friday, June 21, 2002 6:31 AM
Subject: [luau] C struct interdependency problem


> Hi everyone.
>
> I have a question about getting the compiler to grok some files with
> interdependent structs.
>
> I've got something basically like this:
>
> object.h
> -----------
> ...
> typedef struct Object Object;
> typedef struct ObjectError ObjectError;
> ...
> struct ObjectError {
>    Error super_class;
>    ...
> };
> ...
> struct Object {
>    ObjectError *error;
>    ...
> };
> ...
>
> error.h
> ---------
> ...
> typedef struct Error Error;
> ...
> struct Error {
>     Stack super_class;
>     ...
> };
> ...
>
> stack.h
> ----------
> ...
> typedef struct LinkedList LinkedList;
> ...
> struct LinkedList {
>     Object superclass;
>     ...
> };
> ...
>
> So basically the dependency tree is this:
>
> +-----Object-----+<----+
> |/////has-a://///|     |
> |//////...///////|     |
> |//ObjectError///|     |
> |//////...///////|     |
> +----------------+     |
>         +--------------+
>         |
>         .
> +---LinkedList---+<----+
> |/////has-a://///|     |
> |//////...///////|     |
> +----------------+     |
>         +--------------+
>         |
>         .
> +-----Stack------+<----+
> |/////has-a://///|     |
> |//////...///////|     |
> +----------------+     |
>         +--------------+
>         |
>         .
> +--ObjectError---+
> |/////has-a://///|
> |//////...///////|
> +----------------+
>
> Any idea how I can get this setup arranged so the compiler
> believes everything is alright (e.g. where should the #includes
> go and things)?
>
> --Ray
>
> _______________________________________________
> LUAU mailing list
> LUAU at videl.ics.hawaii.edu
> http://videl.ics.hawaii.edu/mailman/listinfo/luau
>




More information about the LUAU mailing list