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

Void Display(void);

};

Производный класс вызывает конструктор базового класса, передавая имя TState() для инициализации строковой части объекта производного класса. После этой операции конструктор сохраняет длинный целый параметр n в закрытым члене производного класса.

Для отображения названия штата и плотности его население вы можете написать замещающую функцию-член Display() следующим образом:

Void tPopulation::Display(void)

{

TState::Display();

cout << “population = =

<< population << ‘\n’ ;

}

Где-нибудь в другом месте программы вы можете создать и использовать объект класса TPopulation для отображения названия штата и плотности население:

TPopulation Nebraska(1570000, “Nebraska”);

Nebraska.Display();

Использование наследования

С помощью наследования можно выводить новые классы, приумножающие свойства уже существующих.

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

Borland С++ содержит расширенную библиотеку классов. один класс с именем TTime разработан специально для событий, связанных со временем. В этой главе вы постройте производный класс, который расширяет TTimer, а также создает класс универсального измерения производительности, который вы можете использовать для тестирования алгоритмов, операций ввода-вывода и другого, критичного к времени выполнения, кода.

Замечание

Класс TTimer (с двумя t) в Borland C++ 3.1 имел имя Timer (с одним Т). определите символ BI-OLDNAMES с помощью директивы #define для компиляции программ, использующих старую форму имен, однако каждый символ имен функций-членов также следует преобразовать а прописной, так что лучше скорректировать программы так, чтобы они могли использовать новые классы. Поскольку TTimer – низкоуровневый по своей природе (он обращается непосредственно к компьютерному оборудованию для обеспечения функций, связанных с отсчетом времени), вы можете использовать этот класс только в программах, написанных для DOS, но не для WINDOWS.

Опуская закрытые члены класса, которые производный класс в любом случае не может использовать. Класс TTimer объявлен в заголовочном файле TIMER.H следующим образом:

class TTimer

{

public:

TTimer(); // Конструктор

void start();

// Начать отсчет времени

void stop();

// Закончить отсчет времени

void reset();

// Отчистит таймер

int status();

// 0= = отсчет времени остановлен; 1==идет отсчет времени

double time();

// Прошедшее время в миллисекундах

static double resolution();

// См. Главу 15

private:

};

Замечание

Программа выводит отсчет о точности таймера:

Resolution: 8.39e-07

0 ms. , actual time = 0.024674 seconds.

100 ms. , actual time = 0.127362 seconds.

200 ms. , actual time = 0.222327 seconds.

300 ms. , actual time = 0.314453 seconds.

400 ms. , actual time = 0.393548 seconds.

500 ms. , actual time = 0.465171 seconds.

600 ms. , actual time = 0.630901 seconds.

700 ms. , actual time = 0.738385 seconds.

800 ms. , actual time = 0.775155 seconds.

900 ms. , actual time = 0.836996 seconds.

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

Создание класса измерения производительность

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

Листинг 3.1 BENCH.H

(объявление класса TBench)

1: // bench.h – Объявление класса TBench

2:

3: #ifndef__ BENCH_H

4: #define__ BENCH_H 1

// Предотвращение нескольких #include

5:

6: #include <classlib\timer.h>

7:

8: typedef void ( * testfn) (void);

9:

10: class TBench: public TTimer {

11: public;

12: TBench(): TTimer() {}

13: void Benchmark(long numTests, testfn tf);

14: void Report(void);

15: };

16:

17: #endif // __ BENCH_H

Класс TBench выводится из TTimer. Конструктор TBench() (строка 12) вызывает конструктор базового класса TTimer, но не выполняет никаких новых операторов для конструирования объекта TBench. Функция-член Benchmark() (строка 13) имеет два параметра – numTests, равный числу тестов, которые необходимо выполнить, и tf, ссылающийся на тестируемую функцию, которая должна иметь тип void и не должна иметь параметров (см. typedef в строке 8). Вторая функция-член Report(), определенная в строке 14, отображает результат теста.

В листинге 3.2 приводится реализация производного класса TBench. Следующая программа демонстрирует использование этого модуля, поэтому не компилируйте его пока.

Листинг 3.2 BENCH.CPP

(реализация класса TBench)

1: // bench.cpp -- реализация класса TBench

2:

3: #include <stdio.h>

4: #include “bench.h”

5:

6: //вызывает тестируемую функцию tf numTests раз

7: void TBench:: Benchmark(long numTests, testfn tf)

8: {

9: printf(“Running %1d tests…”, numTests);

10: Reset(); // Reset timer to zero

11: Start(); // Start timing

12: While (--numTests >= 0)

13: (* tf) (); // call user test function

14: Stop(); // stop timing

15: puts(“\nTests completed”);

16: }

17:

18: // Выводит результаты теста

19: void TBench::Report(void)

20: {

21: double result = Time();

22: if (result < Resolution())

23: puts(“Results too small for accuracy”);

24: printf(“Elapsed time == %6f sec. \n”, result);

25: }

В строках 7-16 реализуется функция-член Benchmark(). После отображения числа выполняемых тестов, функция сбрасывает и запускает таймер с помощью вызова наследованных функций-членов Reset() и Star().

В строках 12-13 вызывается необходимое число раз тестируемая функция, адрес которой хранится в указателе tf . после завершения последнего теста в строке 14 вызывается еще одна наследованная функция-член Stop(), прерывающая отсчет времени. В строке 15 выводится которое сообщение о том, что тесты завершены.

В строках 19-25 реализуется еще одна функция-член TBench – Report(). В строке 21 переменой result присваивается результат наследованной функции-члена Time() в строках 22-23 выводится сообщение о том, что затраченное время слишком мало для того, чтобы его можно было верно ценить. (если у вас возникло подобное сообщение, рекомендуется увеличить число тестов.) В строке 24 отображаются результаты измерений быстродействия в секундах.

Для того чтобы использовать класс TBench, следует создать объект и передать функции-члену Benchmark() число необходимых для выполнения тестов и адрес тестируемой функции. Затем следует вызвать функцию-член Report() . В листинге 3.3 демонстрируется эта последовательность действий, и он может послужить оболочкой для необходимых вам измерений производительности. После компиляции модулей TBENCH.CPP и BENCH.CPP требуется скомпоновать их с библиотечным файлом TCLASDBS.LIB, содержащим скомпилированный код класса TTimer. Если вы пользуетесь автономным компилятором, добавьте следующие две строки в файл TURBOC.CFG, находящийся в текущем каталоге:

3B-IC:\c 45\in Iude

-LC:\c 45\lic

Затем из командной строки DOS введите следующую команду для компиляции модуля BENCH.CPP и тестовой программы TBENCH.CPP, использующей класс TBench:

c tcen h cen h cidss.lic

В дополнение к заданию имен файлов модулей TBENCH и BENCH предыдущая команда передаст компоновщику имя библиотечного файла BC45 – BIDSS.LIB, в котором содержится скомпилированный код класса TTimer. Второй символ S в BIDSS означает малую (small) модуль памяти, используемую в программах для DOS по умолчанию. (в главе 19приводится более подробное объяснение использования моделей памяти в программировании для DOS и WINDOWS). Как уже отмечалось, класс TTimer, из которого выводится TBENCH, обращается к аппаратным средствам способом, не применимым для WINDOWS. Вы должны скомпилировать эту программу в качестве приложения для DOS.

.

Листинг 3.3. TBENCH.CPP

(тестирование класса TBen h)

1: #include<iostream.h>

2: #include<stdio.h>

3: #include ”cen h.h”

4:

5: #define NUMESTS 20000

6:

7: void Testfn((void);

8:

9: main()

10: {

11: TBen h test;

12:

13: out << “Testing sprintf() fun tion\n”;

14: test.Ben hmark(NUMTESTS. Testfn);

15: test.Report();

16: return 0;

17: }

18:

19: void Testfn(void)

20: {

21: har cuffer[80];

22: doucle d = 3.14159;

23:

24: sprintf(cuffer, “%1f” , d)

25: }

В строке 11 объявляется объект класса TBENCH с именем test. Поскольку С++ вызывает конструктор объекта класса (который вызовет конструктор базового класса Timer), вы можете быть уверены, что объект test соответствующим образом проинициализирован и, следовательно, готов к употреблению. После вывода короткого сообщения программа вызывает функцию-член Benchmark() (строка 14) и передает число необходимых для выполнения тестов, а также адрес тестируемой функции. В строке 15 вызывается функция-член Report() объекта test для вывода результатов тестов. Тестируемая функция (строки 19-25) исключительно для демонстрации вызывать функцию sprintf(). Для проведения другого испытания быстродействия заменить содержимое функции testfn() какими-нибудь другими операторами. Выполнение программы приводит к выводу следующего отсчета:

Testing sprintf() function

Running 20000 tests…

Tests completed

Elapsed time = = 4.118690 sec.

Совет

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

Виртуальные функции

виртуальная функция – это функция, вызов которой зависит от типа объекта.

В классическом программировании надо передать объект данных функции, при этом необходимо было задать тип объекта в то время, когда вы писали код.

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

Другими словами, с помощью виртуальных функций объект определяет свои собственные действия.

Замечание

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

важный принцип классов С++, связанных отношением наследования. Согласно правилам С++ указатель на базовой класс может ссылаться на объект этого класса или на объект другого класса, производного от базового (рис. 3.10 и 3.11).

Рис. 3.10. Указатель на базовый класс может ссылаться на объект производного класса

Понимание этого правила – ключ к пониманию того, как используются виртуальные функции.

ПРИМЕР: Рассмотрим ряд классов – А В и С, где В потомок А, а С – потомок B.

A aObject;

// Объявление объекта типа А

B bObject;

// Объявление объекта типа B

C cObject;

// Объявление объекта типа C

Рис. 3.11. Указатель на базовый класс может ссылаться на данные-члены,

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]