The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

4.2 Реализация базового класса — Point

4.2 Реализация базового класса — Point

Предыдущая  Содержание  Следующая V*D*V

Интерфейс абстрактного типа данных в Point.h содержит следующее:

 

extern const void * Point;    /* new(Point, x, y); */

 

void move (void * point, int dx, int dy);

 

Можно снова использовать файлы new.? из главы 2, хотя мы удалим большинство методов и добавим в new.h draw():

 

void * new (const void * class, ...);

void delete (void * item);

void draw (const void * self);

 

Описание типа struct Class в new.r должно соответствовать декларации методов в new.h:

 

struct Class {

    size_t size;

    void * (* ctor) (void * self, va_list * app);

    void * (* dtor) (void * self);

    void (* draw) (const void * self);

};

 

Селектор draw() реализован в new.c. Он заменяет такие селекторы, как differ(), введённые в разделе 2.3, и кодируется в том же стиле:

 

void draw (const void * self) {

    const struct Class * const * cp = self;

 

    assert(self && * cp && (* cp) -> draw);

    (* cp) -> draw(self);

}

 

После этих приготовлений можно обратиться к реальной работе по написанию Point.c, реализации точек. И снова объектно-ориентированный подход помог точно определить, что необходимо сделать: мы должны принять решение о представлении и реализовать конструктор, деструктор, динамически скомпонованный метод draw() и статически скомпонованный метод move(), который представляет собой простую функцию. Если мы придерживаемся двумерной декартовой системы координат, то выбираем очевидное представление:

 

struct Point {

    const void * class;

    int x, y;          /* координаты */

};

 

Конструктор должен проинициализировать координаты .x и .y — теперь совершенно стандартной:

 

static void * Point_ctor (void * _self, va_list * app) {

    struct Point * self = _self;

 

    self -> x = va_arg(* app, int);

    self -> y = va_arg(* app, int);

    return self;

}

 

Оказывается, деструктор не нужен, потому что нет ресурсов, которые должны быть освобождения до того, как delete() удалит саму struct Point. В Point_draw() печатаются текущие координаты в виде, котором их сможет понять pic:

 

static void Point_draw (const void * _self) {

    const struct Point * self = _self;

 

    printf("\".\" at %d,%d\n", self -> x, self -> y);

}

 

Позаботившись о всех динамически скомпонованных методах, можно определить дескриптор типа, где пустой указатель представляет несуществующий деструктор:

 

static const struct Class _Point = {

    sizeof(struct Point), Point_ctor, 0, Point_draw

};

 

const void * Point = & _Point;

 

move() не использует динамическую компоновку, поэтому мы опускаем static, чтобы экспортировать её из Point.c, а её имя не начинается с префикса имени класса Point:

 

void move (void * _self, int dx, int dy) {

    struct Point * self = _self;

    self -> x += dx, self -> y += dy;

}

 

На этом завершается написание кода для точек в Point.? вместе с поддержкой динамической компоновки в new.?.

 

Предыдущая  Содержание  Следующая