- •№1 Объекты и классы
- •Void main ( ) {/* ... */}
- •№5 Конструкторы класса
- •Конструкторы с аргументами
- •№7 Преобразование типов в производных классах
- •№8 Расширение характеристик при наследовании классов
- •Void Display ( ) ;
- •Void Display ( ) { }
- •Void Display ( ) ;
- •№9 Перегрузка и переопределение членов класса
- •№10 Использование виртуальных базовых классов
- •Int value;
№9 Перегрузка и переопределение членов класса
В C++ Перегрузкой называют практику придания функции более чем одного значения. Этот термин означает, что на один и тот же идентификатор нагружено несколько функций. Перегруженные функции уже не различимы по одному только идентификатору (он у них одинаковый). В связи с этим возникают проблемы с таблицами символов, которые решаются с помощью кодирования имен.
Почему следует использовать перегрузку
В C++ с помощью перегрузки можно написать три функции так, что приведенный код будет работоспособен. Каждая функция определяется отдельно от других и отличается от них количеством и типом принимаемых параметров. Концепция перегрузки совсем не нова для языков программирования. Например, оператор = перегружен во многих языках высокого уровня и используется как в операторах присвоения, так и условных операторах, например:
а = b if а = b ...
Перегрузка, распространяясь на концептуально сходные операции, придает C++ особую гибкость, предоставляя тем самым возможность пользователям писать программы с меньшими усилиями. Достоинства перегрузки не достаются даром, и они повышают сложность компилятора, которому теперь приходится больше "думать". Однако точное значение перегруженного идентификатора можно понять только после рассмотрения нескольких соседних слов. В C++ соседними словами являются количество и тип аргументов, используемых при вызове функции. Таким образом, перегрузка применима только к функциям, но не к переменным, классам или типам. Две функции void Display(int); и long Display(int); не различимы и приведут к ошибке компиляции. Перегруженные функции вовсе не обязательно должны быть членами класса. Можно перегружать как функции-члены, так и обычные функции.
Перегруженные функции - не члены
В C++ перегружается любое имя функции, но перегрузка происходит только внутри определенной области видимости. Одна из них — область видимости файла. Любая функция, определенная вне всех классов и без ключевого слова static, имеет область видимости файла. В следующем примере кода используются перегруженные функции Di splay ( ), которые находятся внутри одного и того же файла и имеют область видимости файла:
#include <stdio.h>
void Display (char* string) { puts(string); }
void Display (longvalue) { printf("%ld", value); }
void Display (double value) { printf("%lf, value); }
void main( )
{Display ("\nНапечатай это, пожалуйста");
Display (123456789) ;
Display (3.14159) ;}
Когда компилятор видит различные обращения к Display ( ), он ищет подходящую для использования функцию. Результат такого поиска затем отражается в откомпилированном коде. Вся дополнительная работа выполняется во время компиляции, что очень важно. Это говорит о том, что во время выполнения программы дополнительных затрат не требуется. После создания исполняемого кода обращение к перегруженной функции уже ничем не отличается от обращения к любой другой функции. Так что пользователь имеет все преимущества, связанные с унифицированностью выражений, и не имеет никаких неудобств при увеличении исполняемого кода или затрат времени. Однако сложность выполняемого кода все-таки возрастает, если перегруженная функция вызывается с аргументами, не вполне подходящими любой доступной функции. В таком случае следует быть особенно внимательным. Дело может закончиться ошибкой компиляции или вызовом не той функции.
Перегруженные функции-члены
Поскольку в языке особое внимание уделено концепции классов, основное использование перегрузки связано все-таки с функциями-членами. Когда в классе объявляется несколько функций-членов с одним и тем же именем, говорят, что имя функции в классе перегружено. Нужно обратить внимание на то, что имя функции перегружено именно в классе, а не вообще. Другими словами, область перегруженного имени — это всего один класс. Другие классы могут использовать то же имя, перегружая его иначе или не перегружая вообще. Разные классы — совершенно отдельные области видимости, и компилятор хранит их раздельно. Рассмотрим следующий код:
class Example {
int value;
public:
void Value(int v) { value = v; }
int Valued { return value; }
};
void main( )
{Example e;
e.Value (3) ;
int i = e.Value ( ) ;
Код показывает, что класс Example имеет две перегруженные функции, одну — для записи, а другую — для чтения переменной. Для перегруженных функций это обычное явление. В ANSI С пришлось бы использовать две отдельные функции, такие как putValue ( ) и getValue ( ). C++ позволяет это упростить. Перегруженные функции не обязательно должны быть определены подставляемыми, как показано в примере. Однако типичные функции на чтение и запись переменных определяются именно так. Перегруженные функции должны отличаться по одному или обоим описанным ниже пунктам.
1. Функции должны имеет разное количество аргументов.
2. Отличие должно быть, по крайней мере, в одном из типов аргументов. Как уже говорилось, тип возвращаемого значения не является фактором различия перегруженных функций.