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

9.3 Функции для объектов

9.3 Функции для объектов

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

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

Наша проблема состоит в том, что мы используем переменную указателя для ссылки на объект, но нам нужен вызов функции для создания объекта, если он ещё не существует. Это приводит к чему-то похожему на следующее макропределение:

 

#define Point   (Point ? Point : (Point = initPoint()))

 

Макрос Point проверяет, проинициализировано ли уже описание класса Point. Если нет, для генерации описания класса вызывается initPoint(). К сожалению, если мы определяем Point как макрос без параметров, то больше не сможем использовать то же самое имя как признак структуры для объектов и для соответствующего описания класса. Следующий макрос лучше:

 

#define Class(x)    (x ? x : (x = init ## x ()))

 

Теперь мы определяем Class(Point), чтобы сослаться на описание класса. initPoint() всё ещё вызывает new() как и прежде, но теперь надо возвратить сгенерированное описание класса, то есть для каждого описания класса необходима его собственная функция инициализации:

 

const void * Point;

 

const void * initPoint (void) {

    return new(Class(PointClass),

                "Point", Class(Object), sizeof(struct Point),

                ctor, Point_ctor,

                draw, Point_draw,

                (void *) 0);

}

 

Эта конструкция всё ещё соблюдает порядок, навязанный иерархией классов: сначала описание класса PointClass передано в new(), макрорасширение Class(Point) удостоверяется, что это описание существует. Пример показывает, что для однородности мы должны будем написать пустые функции initObject() и initClass().

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

 

static const void * _Point;

 

const void * const Point (void) {

    return _Point ? _Point :

            (_Point = new(PointClass(),

                "Point", Object(), sizeof(struct Point),

                ctor, Point_ctor,

                draw, Point_draw,

                (void *) 0));

}

 

Мы могли бы переместить определение фактического указателя _Point в функцию; однако, глобальное определение необходимо, если мы всё ещё хотим реализовать munch для System V.

Замена статических объектов функциями не должна быть менее эффективной, чем использование макроса. ANSI-C не разрешает декларацию результата для функции как const или volatile, то есть выделенный жирным шрифтом определитель const в данном примере. (* Первый const указывает, что результат функции указывает на постоянную величину. Только второй const указывает, что константой является значение указателя самого по себе.) GNU-C позволяет такую декларацию и использует её во время оптимизации. Если результат функции const, его значение должно зависеть только от её аргументов, и вызов не должен давать побочных эффектов. Компилятор пытается минимизировать количество вызовов такой функции и использует результаты повторно.

 

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