Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


ЗАМЕНА ВЫРАЖЕНИЙ МАКРОКОМАНДАМИ



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

result = (х*у-3) * (х*у-3) * (х*у-3);

В данном случае программа вычисляет куб выражения (х*у-3). Чтобы улучшить читаемость вашей программы и уменьшить вероятность внесения ошибок из-за опечаток, создайте макрокоманду с именем CUBE, которую ваша программа может использовать следующим образом:

result = CUBE(x*y-3);

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

Для создания макрокоманды вы должны использовать директиву препроцессора # define. Например, следующий оператор создает макрокоманду CUBE:

#define CUBE(x) ((х)*(х)*(х))

Как видите, программа определяет макрокоманду CUBE для умножения параметра х на самого себя дважды. Следующая программа SHOWCUBE.CPP использует макрокоманду CUBE для вывода куба значений от 1 до 10:

#include < iostream.h>

#define CUBE(x) ((x)* (x)* (x))

void main (void)

{
for (int i = 1; i < = 10; i++) cout < < «Для » < < i < < » куб равен «< < CUBE(i) < < endl;
}

При компиляции этой программы препроцессор C++ заменит каждый экземпляр макрокоманды CUBE соответствующим определением. Другими словами, замена макрокоманды препроцессором приведет к следующему коду:

#include < iostream.h>

#define CUBE(x) ((х)*(х)*(х))
void main(void)

{
for (int i = 1; i < = 10; i++) cout < < «Для » < < i < < » куб равен «< < ((i) * (i) * (i)) < < endl;
}

Обратите внимание, что предыдущая макрокоманда поместила параметр х внутрь круглых скобок, использовав запись ((х)*(х)*(х)) вместо (х*х*х).При создании макрокоманд вы должны помещать параметры в круглые скобки, как показано выше, тогда можете быть уверены, что C++ трактует ваши выражения именно так, как вы хотите. Как вы помните из урока 5, C++ использует старшинство операций для определения порядка выполнения арифметических операций. Предположим, например, что программа использует макрокоманду CUBE с выражением 3+5-2, как показано ниже:

result = CUBE(3+5-2);

Если макрокоманда заключает свой параметр в круглые скобки, то препроцессор сгенерирует следующий оператор:

result = ((3+5-2) * (3+5-2) * (3+5-2));

Однако, если в определении макрокоманды опустить круглые скобки, препроцессор сгенерирует следующий оператор:

result = (3+5-2*3+5-2*3+5-2);

Если вы вычислите оба выражения, то обнаружите, что их результаты отличаются. Заключая аргументы макрокоманды в круглые скобки, вы избавитесь от подобных ошибок.

ЧЕМ МАКРОКОМАНДЫ ОТЛИЧАЮТСЯ ОТ ФУНКЦИЙ

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

В случае с макрокомандой препроцессор заменяет в вашем коде каждую ссылку на макрокоманду соответствующим определением макрокоманды. Например, если предыдущая программа использует макрокоманду CUBE в 100 различных местах, препроцессор подставит код макрокоманды 100 раз. Используя макрокоманды, вы избегаете издержек на вызов функции (издержек на помещение параметров в стек и удаление их оттуда, а также издержек на выполнение перехода к коду функции и возврат из него). Это происходит благодаря тому, что в случае с макрокомандой препроцессор встраивает в тело программы соответствующие операторы. Однако, поскольку препроцессор заменяет каждую ссылку на макрокоманду соответствующим кодом, макрокоманды увеличивают размер вашей выполняемой программы.

ИСПОЛЬЗОВАНИЕ МАКРОКОМАНД ПРЕДОСТАВЛЯЕТ БОЛЬШУЮ ГИБКОСТЬ

Вы можете использовать макрокоманды в своих программах различным образом. Однако имейте в виду, что цель использования макрокоманд состоит в упрощении кодирования и улучшении восприятия ваших программ. Следующая программа MACDELAY.CPP иллюстрирует гибкость макрокоманд. Кроме того, эта программа поможет вам лучше представить, как препроцессор заменяет имя макрокоманды соответствующими операторами:

#include < iostream.h>

#define delay(х)

{ \
cout < < «Задержка на » < < х < < endl; \
for (long int i=0; i < х; i++) \
; \
}

void main (void)

{
delay(l00000L);
delay(200000L);
delay(300000L);
}

В данном случае, поскольку определение макрокоманды занимает несколько строк, это определение помещает один символ обратного слэша (\) в конце каждой строки, которая имеет продолжение. Когда препроцессор встретит ссылку на макрокоманду, он заменит эту ссылку операторами, которые появляются в определении макрокоманды.

ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ

Макрокоманды и именованные константы предназначены для улучшения восприятия ваших программ и упрощения программирования. Данный урок описывает создание и использование именованных констант и макрокоманд в ваших кодах. Из урока 38 вы узнаете, что такое полиморфизм, который позволяет объектам изменять форму во время выполнения программы. Однако, прежде чем приступить к уроку 38, убедитесь, что вы освоили следующие основные концепции:

1. Макрокоманды и именованные константы облегчают чтение ваших программ, заменяя сложные выражения и числовые константы смысловыми именами.

2. Заменяя на протяжении всей программы числовые выражения именованными константами, вы уменьшаете количество изменений, которые вам придется выполнить позже, если значение константы потребуется изменить.

3. В процессе компиляции компилятор C++ использует специальную программу, которая называется препроцессором, для замены каждой именованной константы или макрокоманды соответствующим значением.

4. Макрокоманды выполняются быстрее функций, но они увеличивают размер вашей выполняемой программы.

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

Когда программисты говорят о C++ и объектно-ориентированном программировании, то очень часто употребляют термин полиморфизм. В общем случае полиморфизм представляет собой способность объекта изменять форму. Если вы разделите этот термин на части, то обнаружите, что поли означает много, а морфизм относится к изменению формы. Полиморфный объект, следовательно, представляет собой объект, который может принимать разные формы. Этот урок вводит понятие полиморфизма и рассматривает, как использовать полиморфные объекты внутри ваших программ для упрощения и уменьшения кода. К концу данного урока вы освоите следующие основные концепции:

  • Полиморфизм представляет собой способность объекта изменять форму во время выполнения программы.
  • C++ упрощает создание полиморфных объектов.
  • Для создания полиморфных объектов ваши программы должны использовать виртуальные (virtual) функции.
  • Виртуальная (virtual) функция — это функция базового класса, перед именем которой стоит ключевое слово virtual.
  • Любой производный от базового класс может использовать или перегружать виртуальные функции.
  • Для создания полиморфного объекта вам следует использовать указатель на объект базового класса.

ЧТО ТАКОЕ ПОЛИМОРФИЗМ

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

 

class phone

{
public:
void dial(char «number) { cout < < «Набор номера » < < number < < endl; }
void answer(void) { cout < < «Ожидание ответа» < < endl; }
void hangup(void) { cout < < «Звонок выполнен – повесить трубку» < < endl; }
void ring(void) { cout < < «Звонок, звонок, звонок» < < endl; )
phone(char *number) { strcpy(phone:: number, number); };
private:
char number[13];
);

Следующая программа PHONEONE.CPP использует класс phone для создания объекта-телефона:

#include < iostream.h>

#include < string.h>

class phone

{
public:
void dial(char *number) { cout < < «Набор номера » < < number< < endl; }
void answer(void) { cout < < «Ожидание ответа» < < endl; }
void hangup(void) { cout < < «Звонок выполнен – повесить трубку» < < endl; }
void ring(void) { cout < < «Звонок, звонок, звонок» < < endl; }
phone(char *number) { strcpy(phone:: number, number); };
private:
char number[13];
};

void main(void)

{
phone telephone(«555-1212″ );
telephone.dial(«212-555-1212″ );
}

Если вы продемонстрируете программу вашему боссу, то он или она скажет, что ваша программа не делает различий между дисковым и кнопочным телефонами, и что она не поддерживает платные телефоны, когда пользователь должен заплатить 25 центов, чтобы позвонить.

Поскольку вы знаете наследование, то примете решение породить классыtouch_tone и pay_phone из класса phone, как показано ниже:

class touch_tone: phone

{
public:
void dial(char * number) { cout < < «Пик пик Набор номера «< < number < < endl; }
touch_tone(char *number): phone(number) { }
};

class pay_phone: phone

{
public:
void dial(char * number)

{
cout < < «Пожалуйста, оплатите » < < amount < < » центов» < < endl;
cout < < «Набор номера » < < number < < endl;
}

pay_phone(char *number, int amount): phone(number) {pay_phone:: amount = amount; }
private:
int amount;
};

Как видите, классы touch_tone и pay__phone определяют свой собственный метод dial. Если вы предположите, что метод dial класса, phone основан на дисковом телефоне, то вам не потребуется создавать класс для дискового телефона. Следующая программа NEWPHONE.CPP использует эти классы для создания объектов rotary, touch_tone и pay_phone:

#include < iostream.h>

#include < string.h>

class phone

{
public:
void dial(char *number) { cout < < «Набор номера » < < number < < endl; }
void answer(void) { cout < < «Ожидание ответа» < < endl; }
void hangup(void) { cout < < «Звонок выполнен – повесить трубку» < < endl; }
void ring(void) { cout < < «Звонок, звонок, звонок» < < endl; }
phone(char *number) { strcpy(phone:: number, number); };
protected:
char number[13];
);

class touch_tone: phone

{
public:
void dial(char *number) { cout < < «Пик пик Набор номера » < < number < < endl; }
touch_tone(char *number): phone(number) { }
};

class pay_phone: phone

{
public:
void dial(char * number) { cout < < «Пожалуйста, оплатите » < < amount < < » центов» < < endl; cout < < «Набор номера » < < number < < endl; }
pay_phone(char * number, int amount): phone(number) {pay_phone:: amount = amount; }
private:
int amount;
};

void main (void)

{
phone rotary(«303-555-1212″ );
rotary.dial(«602-555-1212″ );
touch_tone telephone(«555-1212″ );
telephone.dial(«212-555-1212″ );
pay_phone city_phone(«555-1111″, 25);
city_phone.dial(«212-555-1212″ );
}

Если вы откомпилируете и запустите эту программу, на экране дисплея появится следующий вывод:

 

С: \> NEWPHONE < Enter>

Набор номера 602-555-1212

Пик пик Набор номера 212-555-1212

Пожалуйста, оплатите 25 центов

Набор номера 212-555-1212

Как уже упоминалось, полиморфный объект представляет собой такой объект, который изменяет форму во время выполнения программы. Предыдущая программа, например, не использовала полиморфные объекты. Иначе говоря, в ней нет объектов, которые бы изменяли форму.

 


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-05-30; Просмотров: 567; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.021 с.)
Главная | Случайная страница | Обратная связь