
- •220300 - Системы автоматизированного проектирования
- •Тема 2. Технологии программирования
- •Тема 2. Технология разработки крупных приложений
- •Структуры
- •Структуры и функции
- •Массивы структур
- •Поиск в массиве структур
- •Вложенность структур
- •Рекурсия
- •Алгоритм быстрой сортировки
- •Массивы структур и бинарные файлы
- •Динамические структуры данных
- •Линейные списки
- •Очереди
- •Контрольная работа
- •Объектно-ориентированное программирование. Классы
- •Конструкторы
- •Перегруженные конструкторы
- •Определение методов класса вне класса
- •Объекты, возвращаемые функцией (методом)
- •Структуры и классы
- •Классы и память
- •Статические данные класса
- •Константные методы
- •Деструкторы
- •Массивы и классы
- •Массивы объектов
- •Строки Строковый тип или стандартный класс string
- •Тип строк AnsiString
- •Перегрузка операций
- •Перегрузка арифметических операций
- •Перегрузка операций сравнения
- •Перегрузка операции приведения типа
- •Преобразования объектов в основные типы и наоборот
- •Преобразование объектов классов в объекты других классов
- •Наследование
- •Конструкторы производного класса
- •Перегрузка функций
- •Иерархия классов
- •Общее и частное наследование. Комбинации доступа
- •Множественное наследование
- •Включение. Классы в классах
- •Виртуальные и дружественные функции
- •Абстрактные классы и чистые виртуальные функции
- •Виртуальные деструкторы
- •Виртуальные базовые классы или устранение неоднозначности при множественном наследовании
- •Дружественные функции
- •Дружественные классы
- •Указатель this
- •Многофайловые программы
- •Распознавание нажатых клавиш
Дружественные функции
Принцип инкапсуляции и ограничения доступа к данным запрещает функциям, не являющимся методами соответствующего класса, доступ к скрытым (private) или защищённым данным объекта. Политика основных принципов ООП такова, что, если функция не является членом класса, она не может пользоваться определённым рядом данных. Тем не менее есть ситуации, когда такая жесткая дискриминация приводит к значительным неудобствам. На протяженнии всего изучения классов мы сталкивались с ситуациями, когда было желательно использовать написанную ранее функцию. Для этого было необходимо создавать методы класса. Рассмотрим пример, демонстрирующий возможность применения процедурной технологии создания программ в объектно-ориентированной программе.
class Int {
private:
int i;
public:
Int() { i=0; }
Int(int ii) { i=ii; }
void show() { cout << i; }
friend Int sum(Int a1, Int a2); // это - не метод, это – дружественная функция
};
//---------------------------------------------------------------------------
int main() {
Int i1(3), i2(7), i3;
i3 = sum(i1, i2);
i3.show();
getch(); return 0;
}
//---------------------------------------------------------------------------
Int sum(Int a1, Int a2) { //классическое определение функции
return (a1.i + a2.i);
}
Рассмотрим другой пример. Допустим необходимо, чтобы функция работала с объектами разных классов. Например, функция должна рассматривать объекты двух классов как аргументы и обрабатывать их скрытые данные. В такой ситуации, в качестве мостов между классами, используют дружественные функции.
class Beta; //нужно для объявления дружественной func
class Alpha {
private:
int data;
public:
Alpha() : data(3) { } //конструктор без аргументов
friend int func(Alpha, Beta); //дружественная функция
};
//---------------------------------------------------------------------------
class Beta {
private:
int data;
public:
Beta() : data(7) { } //конструктор без аргументов
friend int func(Alpha, Beta); //дружественная функция
};
//---------------------------------------------------------------------------
int func(Alpha a, Beta b) //определение функции
{ return( a.data + b.data ); }
//---------------------------------------------------------
int main() {
Alpha aa;
Beta bb;
cout << func(aa, bb) << endl; //вызов функции, увидим 10
getch(); return 0;
}
В этой программе функция int func(Alpha a, Beta b) объявлена в двух классах с ключевым словом friend , что позволяет объяснить компилятору, что она является дружественной, т.е. имеет доступ к скрытым данным двух классов. Объект каждого класса передаётся как параметр функции func(Alpha, Beta), и функция имеет доступ к скрытым данным обоих классов посредством этих аргументов.
Из-за того, что к классу нельзя обращаться до того, как он объявлен в программе, здесь в начале программы мы объявили класс Beta до класса Alpha с помощью следующего оператора: class Beta; .
Надо отметить, что идея дружественных функций несколько сомнительна. С одной стороны, дружественные функции повышают гибкость языка, но, с другой стороны, они не соответствуют принципу ограничения доступа к данным, который гласит, что только функции-члены класса могут иметь доступ к его скрытым данным. Чрезмерное использование дружественных функций не желательно, так как может привести к исчезновению границ между классами и запутанному коду программы.