Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
63
Добавлен:
16.02.2016
Размер:
455 Кб
Скачать

Глава 14

перегрузка функций

Почему следует использовать перегрузку

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

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

#include <iostream.h>

//Перегрузка функции abs()

int abs(int n);

long abs(long 1);

double abs(double d);

main()

{

int n=255; long l=-25L; double d=-15.0L;

cout « "Абсолютная величина " « n «" равна: " « abs(n) « "\n";

cout « "Абсолютная величина " « l «" равна: " « abs(l) « "\n";

cout « "Абсолютная величина” « d «" равна: " « abs(d) « "\n";

return 0;

}

int abs(int n)

{

return n<0? -n:n;

}

long abs(long l)

{

return l<0? -l:l;

}

double abs(double d)

{

return d<0? -d:d;

}

Как известно, библиотека времени выполнения C++ использу­ет три разных функции abs (), labs () и fabs () для вычисле­ния абсолютного значения аргумента. Использование той или другой из них зависит от типа аргумента. Так, в данном примере осуществляется перегрузка функции abs (), что упрощает про­грамму. В зависимости от переданного аргумента вызывается нужный вариант функции.

Этот пример наглядно демонстрирует, как использование перегрузки может упростить код, предоставляя программисту возможность пользоваться одной функцией, которой переда­ются аргументы различного типа. Разумеется, возможность использования перегрузки предъявляет повышенные требова­ния к компилятору.

Чтобы реализовать концепцию перегрузки, разработчикам компиляторов C++ пришлось ввести декорирование имен. По­следнее означает, что все функции в коде программы получают от компилятора имена, основываясь на имени, заданном про­граммистом, и количестве и типах аргументов. Различные компи­ляторы делают это несколько отличным друг от друга образом. Здесь мы опишем, как это делает компилятор фирмы Inprise (ра­нее - фирма Borland): вначале идет имя класса (если речь идет о функции-члене класса), предваряемое символом "@", затем имя функции, снова предваряемое символом "@". У всех идентифи­каторов различается регистр букв. Затем следует последователь­ность символов "@q", начиная с которой идут кодированные обо­значения параметров функции. Для обозначения указателей и ссылок к кодам встроенных типов добавляются буквы "р" и "r", соответственно. Например, если дано такое определение класса:

class AnyClass

{

public:

void SetVal() ;

void SetVal(int);

void SetVal(int, int);

void SetVal(int, int, int);

void SetVal(int&, int, int);

};

компилятор Borland C++ сгенерирует такие имена функций:

@AnyClass@SetVal@qv

@AnyClass@SetVal@qi

@AnyClass@SetVal@qii

@AnyClass@SetVal@qiii

@AnyClass@SetVal@qriii

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

Отсюда видно, что в декорировании имен возвращаемое функцией значение не участвует. Именно по этой причине нельзя перегружать функции, которые отличаются только типом воз­вращаемого значения. Разобраться с тем, как декорирует имена конкретный компилятор достаточно легко. Достаточно потребо­вать от него выдать ассемблерный эквивалент текста программы.

Замечание. Декорирование имен порождает и определенные проблемы. Если нужно написать код, который будет вызываться из программы, написанной на другом языке или даже на другом компиляторе C++, нужно отключить декорирование имен, иначе нужная функция не будет найдена. Это делается с помощью клю­чевого слова extern в форме extern "С" {} Буква "С" здесь напоминает о языке С, в котором декорирования имен не было.

Соседние файлы в папке ЯзыкС++Глушаков