"Michael.Zhang" <zhangqiuyuan@[EMAIL PROTECTED]
> writes:
> [snip: On May 6, 3:32 am, Ben Bacarisse <ben.use...@[EMAIL PROTECTED]
> wrote:
>> "Michael.Z" <zhangqiuy...@[EMAIL PROTECTED]
> writes:
>> > The Table.c was required to be implemented as generic type. If I am
>> > right, Table is declared as void * in header file, the reason is
that,
>> > when used later on, it can be casted to any other type of pointers.
>>
>> > The implementation of Table in Table.c was defined as pointer to
>> > struct Table, because I need to implement the members of Table.
>> ]
>> > My professor told us, void * in header indicates a generic type.
>> > He has some sample codes where List wastypedef'd void pointer but the
>> > definition was struct List Pointer:
>>
>> First, the more common way to "hide the implementation" is simply to
>> declare your functions as using a 'struct Table *' (as has already
>> been explained by Flash Gordon).
>>
>> Secondly, this does not stop you writing generic functions that have a
>> 'void *' parameter. You can pass a 'struct Table *' where a 'void *'
>> is expected when is im****tant to do so.
>
> I just want to make sure I got you right.You are suggesting:
> typedef struct Table{ ...} Table;
> Table * makeTable( void* size, void * data);
Why would a parameter called size be a void *? That is possible, but
I can't say that that is what I was suggesting.
The function makeTable does sound very generic so it is not a good
example. Let's say we have a linked list. To make it generic we
could insist that items to be added are passed as void *:
List *listAdd(List *l, void *item);
We can add a table to a list like this:
List *my_list = makeList(...);
Table *tp = makeTable(...);
...
my_list = listAdd(my_list, tp);
We can insert a list into another list:
List *other = ...;
...
my_list = listAdd(my_list, other);
with not a cast in sight.
>> There is no obvious advantage to making the Table generic (in that
>> sense) rather than simply hidden. In fact there is a positive
>> *disadvantage* to doing that -- you loose all the type-checking. It
>
> I don't quit understand this part.
> "generic(in that sense)": refers to what I said about my professors
> way.
> vs
> "simply hidden": the above example. Table * makeTable( void* size,
> void * data);
That is right. Hiding the details of a struct is a very common and
im****tant technique in C, but doing that by making it look like the
function return a void * is wrong.
From what I've seen so far your teacher's method is just plain wrong.
As a (now ex-) teacher myself, I am loath to be dogmatic -- maybe you
are being asked to write non-****table code for some very specific
reason, but declaring a function to return void * in one place and
defining it to return a Table * in another is undefined behaviour and
will break on some systems.
>> is usually much better to stick with hidden (incomplete) struct
>> pointers right up to the point where you are *forced* to start using
>> 'void *'.
>
>
> an example of being *forced* would be:
>
> void useTable(*void myTable){
> Table * makeTable = (Table *)myTable;
>
> }
>
> if my example is not right, any chance you can give me correct one?
I can't follow that at all. First,did you mean:
void useTable(void *myTable) {
Table * makeTable = (Table *)myTable;
}
If, so the cast is not needed. But anyway, why would you not know the
type of the parameter to a function called useTable? It sounds like
it will always be passed a Table *.
You are forced to use void * when you don't know the type. See
the example about of a generic list. Anything can be added to it
because the item to be added is simply a void *.
--
Ben.


|