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

Infa (1)

.pdf
Скачиваний:
5
Добавлен:
14.04.2015
Размер:
2.31 Mб
Скачать

в аспиранте содержатся все методы и переменные видимости public от person,prepod иstudent

Person *a; Student b; a = &b;

^ сие будет работать. Неизвестно почему, но будет :D

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

вотпример: class Person

{

public:

virtual void printA(); };

void Person::printA()

{

printf("Person\n");

}

class Student:public Person

{

public:

void printA(); };

void Student::printA()

{

printf("Student\n");

}

Student a; Person &b = a; b.printA();

в данном случае выведется "Student"

class Person

{

public:

void printA(); };

void Person::printA()

{

printf("Person\n");

}

class Student:public Person

{

public:

void printA(); };

void Student::printA()

{

printf("Student\n");

}

Student a; Person &b = a; b.printA();

а теперь "Person"

Зачем нужны виртуальные функции При наследовании часто бывает необходимо, чтобы поведение некоторых методов базового

класса и классов-наследников отличались.

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

(кратко vtable) для того, чтобы поддерживать связывание на этапе выполнения программы. Виртуальная таблица — статический массив, который хранит для каждой виртуальной функции указатель на ближайшую в иерархии наследования реализацию этой функции. Ближайшая в иерархии реализация определяется во время выполнения посредством извлечения адреса функции из таблицы методов объекта.

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

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

10) Перегрузка операций.

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

Для перегрузки операций внутри класса нужно написать специальную функцию — метод класса. При перегрузке операций следует помнить следующее:

нельзя поменять приоритет операций;

нельзя изменить тип операции (из унарной операции нельзя сделать бинарную или наоборот);

перегруженная операция является членом класса и может использоваться только в выражениях с объектами своего класса;

нельзя создавать новые операции;

запрещено перегружать операции: . (доступ к членам класса), унарную операцию * (значение по адресу указателя), :: (расширение области видимости), ?: (операция if);

допустима перегрузка следующих операций: +, -, *, /, %, =, <, >, +=, - =, *=, /=,&&, ||, ++, , (), [], new, delete.

Для перегрузки бинарной операции внутри класса необходимо создать функциюметод:

type operator symbols(type1 parametr)

{

операторы;

}

Здесь type — тип возвращаемого операцией значения, operator — служебное слово, symbols — перегруженная операция, type1 - тип второго операнда, первым операндом является экземпляр текущего класса, parametr — имя переменной второго операнда.

Задача

Создать класс для работы с комплексными числами, в котором перегрузить операции

сложения и вычитания. Текст программы с комментариями приведен ниже.

1 #include "stdafx.h"

2 #include <iostream>

3 using namespace std;

4 //класс комплексное число complex

5 class complex

6{

7public:

8//конструктор класса

9complex(bool pr=true);

10//метод, реализующий перегрузку операции сложения

11complex operator +(complex M);

12//метод, реализующий перегрузку операции вычитания

13complex operator -(complex M);

14//действительная часть комплексного числа

15float x;

16//мнимая часть комплексного числа

17float y;

18//метод вывода комплексного числа на экран

19void show_complex();

20};

21//главная функция

22int main()

23{

24setlocale(LC_ALL,"Rus");

25complex chislo, chislo1, chislo2, chislo3(false), chislo4(false);

26//для сложения двух комплексных чисел достаточно использовать

27//операцию +. В классе complex операция + перегружена для

28//выполнения сложения комплексных чисел

29chislo3=chislo1+chislo2;

30cout<<"chislo3 ";

31chislo3.show_complex();

32//для вычитания двух комплексных чисел достаточно использовать

33//операцию -. В классе complex операция - перегружена для

34//выполнения вычитание комплексных чисел

35chislo4=chislo1-chislo2;

36cout<<"chislo4 ";

37chislo4.show_complex();

38system("pause");

39return 1;

40}

41

 

//конструктор класса complex с

логическим параметром (true -

42

 

//по умолчанию).Если параметр равен true, то в конструкторе

43

 

//будут запрашиваться мнимая и

действительная

части числа,

44

 

//если же параметр конструктора равен 0, то будет создаваться

45

 

//комплексное число с нулевыми

действительной

и мнимой частями,

46

 

//Такие числа можно использовать для создания

переменных, в

47

 

//которых будет храниться результат действий с комплексными числами

48

 

complex::complex(bool pr)

 

 

49{

50if (pr)

51{

52cout<<"введите x \t";

53cin>>x;

54cout<<"введите y \t";

55cin>>y;

56show_complex();

57}

58else {x=0; y=0;}

59}

60//метод вывода комплексного числа на экран

61void complex::show_complex()

62{

63if (y>=0) cout<<x<<"+"<<y<<"i"<<endl;

64else cout<<x<<y<<"i"<<endl;

65}

66//метод, реализующий перегрузку операции сложения.

67//Результатом этой функции будет новое комплексное число

68complex complex::operator+(complex M)

69{

70//создаем комплексное число temp, в котором будет храниться

71//результат сложения двух комплек. чисел

72complex temp(false);

73//действительная часть нового комплексного числа формируется

74//как результат сложения действительных частей первого и

75//второго операнда, первым является текущий класс, вторым -

76//передаваемое в функцию комплексное число M

77temp.x=x+M.x;

78//мнимая часть нового комплексного числа формируется как

79//результат сложения мнимых частей первого и второго операнда

80temp.y=y+M.y;

81//возвращаем сумму двух комплексных чисел в качестве результата

82return temp;

83}

84//метод, реализующий перегрузку операции вычитания

85complex complex::operator-(complex M)

86{

87complex temp(false);

88//действительная часть нового комплексного числа формируется

89//как результат вычитания действительных частей первого и

90//второго операнда, первым является текущий класс, вторым -

91//передаваемое в функцию комплексное число M

92temp.x=x-M.x;

93//мнимая часть нового комплексного числа формируется как

94//результат вычитания мнимых частей первого и второго операнда

95temp.y=y-M.y;

96//возвращаем разность двух комплексных чисел

97return temp;

98};

Для перегрузки унарной операции внутри класса необходимо создать функцию-метод:

1

type operator symbols()

2

{

3

операторы;

4

}

 

 

Как Вы помните, в C++ унарные операции ++ и —. Действие этих операций различается при расположении с лева и справа от операнда. Рассмотрим, как реализуется перегрузка операции ++x и x++ на примере класса комплексных чисел. Пусть операция ++x увеличивает действительную и мнимую части комплексного числа x на 1, а x++ увеличивает на 1 только действительную часть комплексного числа x.

1

#include "stdafx.h"

2

#include <iostream>

3 using namespace std;

4 class complex

5

{

6 public:

7 complex(bool pr=true)

8

{

9 if (pr)

10{

11cout<<"введите x \t";

12cin>>x;

13cout<<"введите y \t";

14cin>>y;

15show_complex();

16};

17//функция, перегружающая оператор ++x, в этом случае

18//этот метод без параметров

19complex operator++()

20{

21//увеличиваем действительную и мнимую части на 1

22x++;

23y++;

24//возвращаем текущий класс в качестве результата функции

25return *this;

26}

27//функция, перегружающая оператор x++, в этом случае это

28//метод с абстрактным параметром целого типа.Наличие

29//целого типа в скобках говорит только о том, что

30//перегружается оператор x++, а не ++x

31complex operator++(int)

32{

33//увеличиваем действительную и мнимую части на 1

34x++;

35return *this;

36}

37//метод вывода комплексного числа на экран

38void show_complex()

39{

40if (y>=0) cout<<x<<"+"<<y<<"i"<<endl;

41else cout<<x<<y<<"i"<<endl;

42};

43float x;

44float y;

45};

46int main()

47{

48setlocale(LC_ALL,"Rus");

49//комплексное число chislo2

50complex chislo2;

51//увеличиваем его на 1, вызывая метод complex operator++()

52++chislo2;

53//вывод комплексного числа

54cout<<"++chislo2 = ";

55chislo2.show_complex();

56//увеличиваем его на 1, вызывая метод complex operator++(int)

57chislo2++;

58//вывод комплексного числа

59cout<<"chislo2++ = ";

60chislo2.show_complex();

61system("pause");

62return 1;

63}

Как видно операторы ++x и x++ были перегружены по-разному.

11) Шаблоны функций и классов.

СОЗДАНИЕ ПРОСТОГО ШАБЛОНА ФУНКЦИИ

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

template<class Т>Т mах(Та, Т b)

 

 

{

 

 

 

if

(а>

b)

return(а);

else

 

 

return(b);

}

 

 

 

Буква T данном случае представляет собой общий тип шаблона. После определения шаблона внутри вашей программы вы объявляете прототипы функций для каждого требуемого вам типа. В случае шаблона тах следующие прототипы создают функции типа float и int.

float

max(float,

float);

int max(int, int);

 

 

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

template<class Т>Т max(Та, Т b)

{

 

 

 

 

 

if

(a

 

>

b) return(а)

;

else return(b);

 

 

 

 

 

}

 

 

 

 

 

float max(float a, float b)

 

 

 

 

{

 

 

 

 

 

if

(a

>

b)

return(a)

;

else

 

 

 

 

return(b);

}

 

 

 

 

 

Следующая программа МАХ_ТЕМР.СРР использует шаблон тах для создания функции типа int и float.

#include <iostream.h>

template<class T>Т mах(Та, Т b)

 

 

 

{

 

 

 

 

if

(a

>

b)

return(a);

else

 

 

 

return(b);

}

 

 

 

 

float max(float, float);

int max(int, int);

void main(void)

{

 

 

 

 

 

 

 

 

 

 

 

cout<<

"Максимум

100

и

200

равен

"

<<

max(100,

200)

<<

endl;

cout <<

"Максимум

5.4321

и

1.2345

равен

"

<<

max(5.4321,

1.2345)

<<

endl;

}

 

 

 

 

 

 

 

 

 

 

 

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

13.

Использование шаблонов функций

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

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

ШАБЛОНЫ, КОТОРЫЕ ИСПОЛЬЗУЮТ НЕСКОЛЬКО ТИПОВ

Предыдущее определение шаблона для функции max использовало единственный общий тип Т. Очень часто в шаблоне функции требуется указать несколько типов. Например, следующие операторы создают шаблон для функции show_array, которая выводит элементы массива. Шаблон использует тип Т для определения типа массива и тип Т1 для указания типа параметра count:

template<class T,class T1> void show_array(T *array,T1 count)

{

T1

 

index;

for (index =0; index < count;

index++)

cout <<array[index] << ' ';

cout

<<

endl;

}

Как и ранее, программа должна указать прототипы функций для требуемых типов:

void

show_array(int

*,

int);

void show_array(float *, unsigned);

 

 

Следующая программа SHOW_TEM.CPP использует шаблон для создания функций, которые выводят массивы типа int и типа float.

#include <iostream.h>

template<class T,class T1> void show_array( T *array,T1 count)

{

T1

 

index;

for (index

=0; index < count; index++) cout <<array[index] “

' ';

cout

<<

endl;

}

void show_array(int *, int);

void show_array(float *, unsigned);

void main(void)

{

 

 

 

 

 

 

 

 

 

int

pages[]

=

{

100,

200,

300,

400,

500

};

float

pricesH

 

=

{

10.05,

20.10,

 

30.15

};

show_array(pages,

 

 

 

 

 

 

 

5);

show_array(prices,

 

 

 

 

 

 

 

3);

}

 

 

 

 

 

 

 

 

 

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