- •Часть II Объектно-ориентированное проектирование Конспект лекций
- •Процесс разработки пп
- •Пример ооПр (объектно-ориентированного проектирования)
- •Определение объектно-ориентированного языка программирования (оояп)
- •Разработка класса в ооп.
- •Уровни видимости
- •Методы класса
- •Конструкторы и деструктор
- •Объявление методов класса
- •Реализация класса: общие положения
- •Определение конструкторов: примеры
- •Определение методов класса
- •Использование класса
- •Примеры использования класса
- •Перегрузка функций
- •Перегрузка операций
- •Выбор функции
- •Друзья класса
- •Друзья или члены
- •Преобразования типа
Друзья или члены
Любой метод, за некоторыми (небольшими) исключениями (к ним относятся конструкторы, деструктор и кое-что еще), представляющий интерфейс класса, может быть реализован и функцией-членом, и функцией-другом класса.
Общее:
имеют доступ к закрытой части класса,
хотя бы один аргумент - экземпляр класса
Различие:
член |
друг |
|
|
|
|
|
|
Rational x(1,3); x + 1 - все в порядке 1 + x - ошибка! |
Rational x(1,3); x + 1 - все в порядке 1 + x - все в порядке |
Функции-члены класса:
конструкторы, деструкторы, виртуальные функции;
операции, требующие в качестве операндов основных типов lvalue (например, =, +=, ++ и т.д.)( левый операнд должен быть адресным (value) выражением)
операции, изменяющие состояние объекта
Функции-друзья класса:
операции, требующие неявного преобразования операндов (например, +, - и т.д.)
операции, первый операнд которых не соответствует типу экземпляра класса (например, << и >>).
При прочих равных условиях лучше выбирать функции-члены класса.
Преобразования типа
Возможны два способа преобразования типа для вновь создаваемого класса: преобразование из уже существующего типа в новый и преобразование нового разрабатываемого типа в уже существующий.
Из существующего типа в новый - с помощью одноаргументного конструктора.
Каждый конструктор с одним аргументом любого типа выполняет преобразование типа - из типа аргумента в тип класса. Конструктор может вызываться явно или неявно.
Пример для класса Rational:
Rational x = Rational(23); // явный вызов
Rational y = 23; // неявный вызов
Возможны любые использования, в том числе и при вычислении выражений с использованием перегруженных операций: можно определить одну операцию сложения Rational с Rational; она должна быть реализована как функция-друг класса (т.к. первым аргументом может и не быть экземпляр класса - допускаются преобразования типа int в тип Rational):
friend Rational operator + (Rational, Rational);
Rational a(1,2), b(1), c;
c = a + b;
c = a + 1; // эквивалентно c = a + Rational(1);
c = 2 + a; // эквивалентно c = Rational(2) + a;
Из нового типа в существующий - с помощью перегрузки операции преобразования типа
Обязательно функция-член класса.
Прототип: operator имя_типа ();
Реализация: имя_класса::operator имя_типа() { ... }
Использование: неявно при вычислении выражений или явно с помощью обычной операции преобразования типа: имя_типа(выражение).
Пример для класса Rational:
class Rational{
public:
...
operator float() { return (float) num / den; }
...
};
Использование:
Rational x(3,2);
float f = x;
Еще пример:
while( cin >> n)
cout << n;
Возможные неприятности:
Если в классе Rational есть одноаргументный конструктор (преобразование int в Rational) и в нем будет перегружена операция преобразования типа для int (преобразование Rational в int), тогда конструкция:
Rational a(1,2);
... a + 1 ...
вызовет сообщение об ошибке (два преобразования типа, определенные пользователем - что выбрать: int + int или Rational + Rational?
