ADT

Тема в разделе "LANGS.C", создана пользователем osox, 23 май 2010.

  1. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    Всех приветствую хочу с Вами посоветоватся относительно языка С
    а точнее хочу что бы Вы поделились опытом относительно
    организации интерфейса для различных ADT
    возмем для примера очередь для всех примеров чтобы
    сконцентрироватся именно на интерфейсе
    я часто вижу три варианта реализации интерфейса

    вариант 1
    в заголовочном файле определяем структуру
    Код (Text):
    1. typedef queue
    2. {
    3.     //...  все поля видимы для кода
    4.     //...  который использует интерфейс
    5. } queue;
    удобно в плане прямого доступа к нужным полям но некоторые поля
    можно было бы и скрыть так как они используются только для
    реализации другие же очень удобно использовать напрямую
    в клиентском коде

    вариант 2
    в заголовочном файле определяем структуру
    но не со всеми полями которые реально существуют в объекте
    а только с теми к которым нужно и удобно обращатся из
    клиентского кода например так сделано в GLIB
    пример
    Код (Text):
    1. typedef queue
    2. {
    3.    //...только то что нужно видеть в интерфейсе
    4. } queue;
    а в файле реализации уже определяем полную структуру
    Код (Text):
    1. typedef real_queue
    2. {
    3.    //...интерфейсная чаcть
    4.    //...служебные данные
    5. } real_queue;
    6. queue* dummy(queue *q)
    7. {
    8.     real_queue qe = (real_queue*)q;
    9.     // ...processing ...
    10.     return (queue*)qe;
    11. }
    так реализованы некоторые ADT в GLIB интересный подход
    в клиентском коде есть доступ к внутренним полям но только к видимым
    и которые реально нужны бывают в клиентском коде

    вариант 3
    встречаются и такие реализации
    в заголовочном файле объявляем неполный тип
    Код (Text):
    1. struct queue;
    фактически в клиентском коде можно использовать только указатель
    и только для прима перадачи его интерфейсу

    кто что использует ? может можно как то лучше делать ?
    я конечно понимаю что по большей части выбор представления
    определяет сам ADT с учетом его характеристик но хотелось бы Вас
    послушать и чему то научится у Вас :)
     
  2. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    typedef struct { ... } common_interface_t;

    typedef struct {
    common_interface_t common;

    .....
    } specific_thing_1_t;

    typedef struct {
    common_interface_t common;

    .....
    } specific_thing_2_t;

    ...

    #define SPECIFY_THIS_THING(typ, ptr) ((typ*)ptr)
    #define INTERFACE_THIS_THING(ptr) (&(ptr->common))

    итд.

    такой подход используется много где. например, в параметрах Х вынь сообщений. в связи лимбо адт и С частей. кстати, откуда словцо то? я такое название классов мало где встречал.
     
  3. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    qqwe

    словцо ADT ?
     
  4. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    изврат ?

    Код (Text):
    1. /* Object Orientation in C */
    2. /* Contributed by Jim Weirich */
    3. /* Edit osox */
    4. #include <stdio.h>
    5. #include <stdlib.h>
    6.  
    7. /* abstract interface declaration */
    8.  
    9. struct Shape {
    10.     struct ShapeFuncTable *funcTable;
    11.     void *privateData;
    12. };
    13.  
    14. struct ShapeFuncTable {
    15.     void (*Draw)(struct Shape * obj);
    16.     void (*MoveTo)(struct Shape * obj, int newx, int newy);
    17.     void (*RMoveTo)(struct Shape * obj, int dx, int dy);
    18. };
    19.  
    20.  
    21. /* Class Rectangle */
    22.  
    23. struct RectanglePrivateData {
    24.     int x, y;
    25.     int width;
    26.     int height;
    27. };
    28.  
    29. void RectangleDraw (struct Shape * obj)
    30. {
    31.     struct RectanglePrivateData * rdata =
    32.     (struct RectanglePrivateData*)obj->privateData;
    33.     printf ("Drawing a Rectangle at (%d,%d), width %d, height %d\n",
    34.         rdata->x, rdata->y, rdata->width, rdata->height);
    35. }
    36.  
    37. void RectangleMoveTo (struct Shape * obj, int newx, int newy)
    38. {
    39.     struct RectanglePrivateData * rdata =
    40.     (struct RectanglePrivateData*)obj->privateData;
    41.     rdata->x = newx;
    42.     rdata->y = newy;
    43. }
    44.  
    45. void RectangleRMoveTo (struct Shape * obj, int dx, int dy)
    46. {
    47.     struct RectanglePrivateData * rdata =
    48.     (struct RectanglePrivateData*)obj->privateData;
    49.     rdata->x += dx;
    50.     rdata->y += dy;
    51. }
    52.  
    53. void RectangleSetWidth (struct Shape * obj, int newWidth)
    54. {
    55.     struct RectanglePrivateData * rdata =
    56.     (struct RectanglePrivateData*)obj->privateData;
    57.     rdata->width = newWidth;
    58. }
    59.  
    60. void RectangleSetHeight (struct Shape * obj, int newHeight)
    61. {
    62.     struct RectanglePrivateData * rdata =
    63.     (struct RectanglePrivateData*)obj->privateData;
    64.     rdata->height = newHeight;
    65. }
    66.  
    67. struct RectangleFuncTable {
    68.     void (*Draw)(struct Shape * obj);
    69.     void (*MoveTo)(struct Shape * obj, int newx, int newy);
    70.     void (*RMoveTo)(struct Shape * obj, int dx, int dy);
    71.     void (*SetWidth)(struct Shape * obj, int width);
    72.     void (*SetHeight)(struct Shape * obj, int height);
    73. } rectangleFuncTable = {
    74.     RectangleDraw,
    75.     RectangleMoveTo,
    76.     RectangleRMoveTo,
    77.     RectangleSetWidth,
    78.     RectangleSetHeight
    79. };
    80.  
    81. struct Shape * MakeRectangle (
    82.     int initx,
    83.     int inity,
    84.     int initw,
    85.     int inith)
    86. {
    87.     struct Shape * obj = malloc (sizeof *obj);
    88.     struct RectanglePrivateData * rdata = malloc (sizeof *rdata);
    89.     obj->funcTable = (struct ShapeFuncTable*) &rectangleFuncTable;
    90.     obj->privateData = rdata;
    91.  
    92.     rdata->x = initx;
    93.     rdata->y = inity;
    94.     rdata->width = initw;
    95.     rdata->height = inith;
    96.  
    97.     return obj;
    98. }
    99.  
    100.  
    101. /* Class Circle */
    102.  
    103. struct CirclePrivateData {
    104.     int x, y;
    105.     int radius;
    106. };
    107.  
    108. void CircleDraw (struct Shape * obj)
    109. {
    110.     struct CirclePrivateData * cdata =
    111.     (struct CirclePrivateData*)obj->privateData;
    112.     printf ("Drawing a Circle at (%d,%d), radius %d\n",
    113.         cdata->x, cdata->y, cdata->radius);
    114. }
    115.  
    116. void CircleMoveTo (struct Shape * obj, int newx, int newy)
    117. {
    118.     struct CirclePrivateData * cdata =
    119.     (struct CirclePrivateData*)obj->privateData;
    120.     cdata->x = newx;
    121.     cdata->y = newy;
    122. }
    123.  
    124. void CircleRMoveTo (struct Shape * obj, int dx, int dy)
    125. {
    126.     struct CirclePrivateData * cdata =
    127.     (struct CirclePrivateData*)obj->privateData;
    128.     cdata->x += dx;
    129.     cdata->y += dy;
    130. }
    131.  
    132. void CircleSetRadius (struct Shape * obj, int newRadius)
    133. {
    134.     struct CirclePrivateData * cdata =
    135.     (struct CirclePrivateData*)obj->privateData;
    136.     cdata->radius = newRadius;
    137. }
    138.  
    139. struct CircleFuncTable {
    140.     void (*Draw)(struct Shape * obj);
    141.     void (*MoveTo)(struct Shape * obj, int newx, int newy);
    142.     void (*RMoveTo)(struct Shape * obj, int dx, int dy);
    143.     void (*SetRadius)(struct Shape * obj, int width);
    144. } circleFuncTable = {
    145.     CircleDraw,
    146.     CircleMoveTo,
    147.     CircleRMoveTo,
    148.     CircleSetRadius
    149. };
    150.  
    151. struct Shape * MakeCircle (int initx, int inity, int initr)
    152. {
    153.     struct Shape * obj = malloc (sizeof *obj);
    154.     struct CirclePrivateData * cdata = malloc (sizeof *cdata);
    155.     obj->funcTable = (struct ShapeFuncTable*) &circleFuncTable;
    156.     obj->privateData = cdata;
    157.  
    158.     cdata->x = initx;
    159.     cdata->y = inity;
    160.     cdata->radius = initr;
    161.  
    162.     return obj;
    163. }
    164.  
    165.  
    166. /* ===================================================================
    167.  * DoSomethingWithShape is a fuction that takes a polymorphic shape
    168.  * and manipulates it according to its interface.  It doesn't care if
    169.  * shape is a circle or a rectangle, as long as it conforms to the
    170.  * shape interface.
    171.  *
    172.  * If we would pull the shape interface into a separate header file
    173.  * and move this function into its own ".c" file (that referenced the
    174.  * Shape only definitions), then we could add new shapes without
    175.  * changing a single line of source code in this function, yet the
    176.  * function would still handle shapes that were defined by the user.
    177.  */
    178.  
    179. void DoSomethingWithShape (struct Shape * s)
    180. {
    181.     s->funcTable->Draw (s);
    182.     s->funcTable->RMoveTo (s, 100, 100);
    183.     s->funcTable->Draw (s);
    184. }
    185.  
    186.  
    187. /* ===================================================================
    188.  * Main Program
    189.  */
    190.  
    191. void test_draw(struct Shape *t)
    192. {
    193.     t->funcTable->Draw(t);
    194. }
    195.  
    196. typedef struct Shape Rectangle;
    197. typedef struct Shape Circle;
    198.  
    199. void Draw(struct Shape *Obj)
    200. {
    201.     Obj->funcTable->Draw(Obj);
    202. }
    203.  
    204. void SetWidth (struct Shape * obj, int newWidth)
    205. {
    206.     struct RectanglePrivateData * rdata =
    207.     (struct RectanglePrivateData*)obj->privateData;
    208.     rdata->width = newWidth;
    209. }
    юзать так :)

    Код (Text):
    1. int main ()
    2. {
    3.     Rectangle *Rect = MakeRectangle (10, 20, 5, 6);
    4.     Circle *Circ = MakeCircle (15, 25, 8);
    5.  
    6.     /* using shapes polymorphically */
    7.    
    8.     Draw(Rect); /* req->pVtbl->Draw() */
    9.     Draw(Circ); /* circ->pVtbl->Draw() */
    10.  
    11.     /* access a rectangle specific function */
    12.    
    13.     SetWidth(Rect, 250); /* req->pPrivateData->width */
    14.  
    15.     /* using shapes polymorphically */
    16.    
    17.     Draw(Rect); /* req->pVtbl->Draw() */
    18.  
    19.     return 0;
    20. }
    вот еще бы как нибудь избавится от передачи ссылки на объект
    тоесть не так
    Draw(Rect); /* req->pVtbl->Draw() */
    Draw(Circ); /* circ->pVtbl->Draw() */
    а так
    Rect.Draw(); /* req->pVtbl->Draw() */
    Circ.Draw(); /* circ->pVtbl->Draw() */
    :)
     
  5. W4FhLF

    W4FhLF New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2006
    Сообщения:
    1.050
    лол )

    Изобрёл полиморфизм. Писать на С++ компиляторе и изобретать такие велосипеды. Похвально. :)
     
  6. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Хотел статический полиморфизм, изобрел динамический. Скоро изобретение С++.
     
  7. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    osox
    да
    нет. нормально. только декларацию типа и выделение/заполнение переменных лучше разделять.
    и для доступа к вариантам лучше использовать макросы. во первых писать меньше, а во вторых читабельнее

    W4FhLF J0E
    некоторые оч распространенные языки программирования позволяют следующие конструкции

    a = 2
    a = "n = " + (a + 3)
    a = ( "".join(a, "\n-------------"), 18)
    print a[0]

    зачем использовать с++ где все так сложно по сравнению с ^?
    как вы догадываетесь, на уровне реализации это самый настоящий полиморфизм. (причем, писано там все на с). причем, в беседах с адептами вышеприведенного языка постоянно сталкиваешься с ихним полным нежеланием вникать в детали реализации, даже ради получаемых от этого бонусов. в разговорах они, как правило, постоянно применяют магическое слово "классы", которых на уровне вм как раз и нет. но увидеть это не вникая в подробности реализации невозможно.

    если подобных полиморфизмов немного, а код достаточно сложнее хеловорда, то отказ от с++ увеличит скорость и уменьшит размеры. кроме того, с более портабелен и портирован чем с++. например, я знаю небольшие встраиваемые и пригодные для встраивания компиляторы с, но ни одного с++. далее, код на с может быть достаточно легко перенесен на многие языки-потомки. чего не скажешь о с++.
    таким образом, с++ это не лучший, а просто другой вариант. есть и другие другие. но вопрос был по С. ответ, видимо, ожидается тоже по С
     
  8. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Что бы иметь статическую типизацию, перенести часть ошибок из run time в compile time.
    Голословное утверждение. За счет чего?
    Это под Windows
    Вопрос был про полиморфизм времени компиляции, ответ был про полиморфизм времени выполнения. Мой намек был изучить разницу.
     
  9. sveta

    sveta SVETA7.0.1-2010

    Публикаций:
    0
    Регистрация:
    12 дек 2008
    Сообщения:
    74
    >>qqwe
    >откуда словцо то
    АДТ Абстрактные Типы Данных ( jafa )