- •Объявление и определение класса.
- •Конструкторы и деструкторы ( типы конструкторов и деструкторов)
- •Дружественные функции.
- •Пеpегpузка опеpаций ( синтаксис operator)
- •Статические компоненты класса.
- •Пространства имен.
- •Иерархия классов ( последовательность работы конструкторов и деструкторов )
- •Шаблоны ( пример template)
- •Доступ к наследуемым компонентам
- •Виртуальные функции (когда применяются, форма вызова)
- •Ввод-вывод в файл. Сохранение объектов в файле.
- •Обработка исключений (блоки try, throw, catch)
- •Использование классов при организации исключений. Иерархия исключений
- •Паттерны и их классификация
- •Абстрактная фабрика.
- •Наблюдатель.
- •Классификация типов данных.
- •Массивы и строки. Оператор foreach
- •Классы, создание объектов.
- •Методы класса и их параметры.
- •Свойства класса.
- •Наследование и виртуальные функции. Механизмы наследования
- •Классы – интерфейсы.
- •Производные классы
- •Методы - члены класса
- •Виртуальные методы
- •Делегаты.
- •Создаем собственный делегат
Дружественные функции.
Функция, объявленная в производном классе, может иметь доступ только к защищенным (protected) или общим (public) компонентам базового класса.
Функция, объявленная вне класса, может иметь доступ только к общим (public) компонентам класса и обращаться к ним по имени, уточненному именем объекта или указателя на объект.
Чтобы получить доступ к личным компонентам объектов некоторого класса Х в функции, не имеющей к ним доступа, эта функция должна быть объявлена дружественной в классе X:
class X
{ friend void Y:: fprv( int, char*);
/* Другие компоненты класса X */
}
Можно объявить все функции класса Y дружественными в классе X;
class Y;
class X
{ friend Y;
/* Другие компоненты класса X */
}
class Y
{ void fy1(int, int);
int fy2( char*, int);
/* Другие компоненты класса Y */
}
Дружественной может быть и функция, не являющаяся компонентой какого-либо класса, например,
class XX
{ friend int printXX ( );
/* Другие компоненты класса ХХ */
}
Здесь функция printXX имеет доступ ко всем компонентам класса XX, независимо от закрепленного за ними уровня доступа.
В теории объектно-ориентированного программирования считается, что при хорошо спроектированной системе классов не должно быть необходимости в дружественных функциях, однако в ряде случаев их использование упрощает понимание и последующие модификации программы.
Пеpегpузка опеpаций ( синтаксис operator)
В языках программирования определена семантика операций, выполняемых над базовыми (предопределенными) типами данных, например, если x, y и z - переменные типа float, то запись x = y + z; предполагает интуитивно очевидные действия, сложение x и y и присваивание переменной z полученной суммы. Желательно было бы и для типов, определяемых в программе, в том числе для классов, определить семантику и алгоритмы операций сложения, вычитания, умножения и т.д., чтобы иметь возможность вместо вызова соответствующих функций записывать просто x + y и в случае, когда x и y являются объектами некоторых классов. В C++ это достигается переопределением имеющихся в языке операций для других типов данных.
Переопределенная операция объявляется так:
тип_результата operator знак_операции (формальные параметры)
{ описание_алгоритма_выполнения_операции }
Например:
class TPoint
{ int x,y;
public:
TPoint& operator+=( const TPoint& adder );
TPoint& operator-=( const TPoint& subber );
friend TPoint operator - ( const TPoint& one, const TPoint& two);
friend TPoint operator + ( const TPoint& one, const TPoint& two);
friend int operator == ( const TPoint& one, const TPoint& two);
friend int operator != ( const TPoint& one, const TPoint& two);
};
Полное определение этих операций для объектов класса TPoint имеет вид:
inline TPoint& TPoint::operator += ( const TPoint& adder )
{ x += adder.x; y += adder.y; return *this;}
inline TPoint& TPoint::operator -= ( const TPoint& subber )
{ x -= subber.x; y -= subber.y; return *this;}
Остальные операции определяются аналогичным образом.
Пусть в программе имеются объявления:
TPoint x(12,3), y(21,30), z(18,30);
Тогда можно записать: x +=y; y-=z; TPoint r = x + z:
Общие правила переопределения операций сводятся к следующему:
- Двуместные операции должны иметь два параметра, одноместные - один параметр, причем, если операция объявлена как компонента класса, то неявным первым операндом является экземпляр объекта (следовательно при определении двуместной операции будет задаваться один параметр, одноместная операция объявляется с пустым списком параметров). Если операция переопределяется вне класса (с описателем friend ), то для двуместной операции должны быть заданы два параметра, для одноместной операции - один параметр.
- При переопределении сохраняется приоритет исходной операции т.е. операция + будет выполняться раньше операции = и т.д.
- При переопределении не наследуются свойства коммутативности и ассциативности, т.е. результат выражения х + y - z может отличаться от результата выражения y - z + x и зависит от того, как определены соответствующие операции.
- Не допускается переопределение операций . (точка), .* ( точка -звездочка, обращение к указателю на компоненту класса или структуры), :: (разрешение контекста), а также операции # и ##, используемые при препроцессорной обработке.
- Переопределяемые операции = (присваивание), () (функция), [ ] (индекс), -> (обращение к компоненте класса по указателю) всегда должны быть компонентами класса и не могут быть static.
- Переопределяемые операции new и delete должны быть static - компонентами класса.
В остальном к переопределяемым операциям предъявляются те же требования, что и к функциям.
