Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции C++.doc
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
1.44 Mб
Скачать

Глава 4. Перегрузка функций и операторов

В прошлой главе кратко обсуждалась перегрузка функций и операторов, являющаяся важнейшей особенностью языка C++. В этой главе мы подробно рассмотрим вопросы, связанные с перегрузкой. Также в ходе этого обсуждения будут затронуты и смежные вопросы.

4.1 Перегрузка конструкторов

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

Начнем с примера. В следующей программе объявляется класс timer, действующий как таймер обратного отсчета. При создании объекта типа timer ему присваивается начальное значение вре­мени. В результате вызова функции run() таймер начинает отсчет в сторону уменьшающихся зна­чений, пока не достигнет значения 0. В данном примере конструк­тор перегружен для того, чтобы можно было указывать время в секундах с помощью целого числа или строки, или в минутах и секундах, если указываются два целых числа.

Эта программа использует библиотечную функцию clock(), возвращающую число тиков, про­шедших с момента запуска программы. Поделив это значение на макрос CLOCKS_PER_SEC, получаем значение в секундах. Прототип clock() и макрос CLOCKS_PER_SEC содержатся в заголовочном файле time.h.

#include <iostream.h>

#include <stdlib.h>

#include <time.h>

class timer

{

int seconds;

public:

timer(char *t) { seconds = atoi(t); }

timer(int t) { seconds = t; }

timer(int min, int sec) { seconds = min*60 + sec; }

void run();

};

void timer::run()

{

clock_t t1, t2;

t1 = t2 = clock()/CLOCKS_PER_SEC;

while(seconds)

{

if(t1+1 <= (t2=(clock()/CLOCKS_PER_SEC)))

{

seconds--; t1 = t2;

}

}

cout << "\a"; // звонок

}

int main()

{

timer a(10), b("20"), c(1, 10);

a.run(); // отсчитать 10 секунд

b.run(); // отсчитать 20 секунд

с.run(); // отсчитать 1 минуту 10 секунд

return 0;

}

Как можно видеть, при создании объектов a, b и с внутри функции main() они получают началь­ное значение с использованием трех различных методов, поддерживаемых перегруженными кон­структорами. Каждый из них позволяет провести инициализацию для соответствующих данных.

4.2 Локализация переменных

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

void f()

{

int i;

i = 10;

int j;

/* ... */

}

Поскольку оператор присваивания i=10 попадает между двумя объявлениями i и j, то компиля­тор С выдаст ошибку и откажется компилировать эту функцию. Однако в C++ этот фрагмент абсолютно приемлем, и компилятор не обнаружит ошибки. В C++ локальная переменная может объявляться где угодно в блоке. Более того, она оказывается известной только тому коду, кото­рый следует после нее в блоке.

Ниже представлен другой пример, показывающий, каким способом локальные переменные могут объявляться в блоке при использовании языка C++:

#include <iostream.h>

#include <string.h>

int main()

{

int i;

i = 10;

int j = 100; // совершенно корректно в C++

cout << i*j << "\n";

cout << "Enter a string: ";

char str[80]; // также корректно в C++

cin >> str;

// вывод строки в обратном порядке

int k;

k = strlen(str) - 1;

while(к>=0) cout << str[k--];

return 0;

}

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