
- •Oop и типы данных. Основные особенности ооп.
- •Инкапсуляция. Классы и структуры.
- •9.Подходы к выделению объектов, их свойств и методов оперирования.
- •10. Уточнение характеристик объектов и редактирование их определений.
- •11. Образцы и типовые проекты при ооп.
- •12. Именование объектов и методов. Коллекции отлаженных заготовок.
- •14. Компоненты: объекты, субъекты, аспекты.
- •15. Подходы к декомпозиции программ и накоплению компонент программ
- •16. Контекст исполнения многократно используемых компонент.
- •17. Проблема версифицирования программы в процессе разработки
- •18. Перенос компонент в разные системы //возможно предыдущее подойдет
- •19. Факторизация программ и программных компонент
- •20. Жизненный цикл программ (жцп). Фазы, этапы и стадии разработки программ
- •Сопровождение
- •Классические схемы жцп. Последовательная модель жцп
- •Каскадная модель жцп. Условия завершения фаз жцп
- •Табличная модель Хантера совмещения фаз жцп.
- •Uml. Диаграммы объектов и диаграммы размещения
- •Термины и понятия
- •Общие свойства
- •Содержание
- •Uml. Временные диаграммы
- •Технологичные последовательности и техника самодокументирования.
- •Основные идеи экстремального программирования
- •Многократность и рефакторинг при разработке программ. Многократность
- •Рефакторинг
- •«Парный» эффект и обе5спечение устойчивости разработки.
- •Коллективное владение
- •2. Ссылки, указатели и переменные – отличия при использовании
- •4. Зачем нужны описатели public и private?
- •5. Перегрузка операций. Пример.
- •6. Роль ссылок в борьбе за эффективность. Пример.
- •7. Инициализация объектов. Варианты конструкторов. Пример
- •8. Указатели и вектора. Сравнение стиля доступа к компонентам
- •9. Что дает использование inline?
- •10. Производные классы. Наследование.
- •11. Деструкторы. Зачем они нужны?
- •12. Друзья
- •13. Левосторонние значения (lvalue)
- •14. Описатель const. Его влияние на присваивание значений. Пример
- •15. Объединение типов данных. Пример полезного применения
- •16. Управление видимостью членов класса и доступам к элементам объекта.
- •17. Ссылка на себя //this
- •18. Освобождение памяти от лишних объектов
- •19. Порядок выполнения конструкторов и деструкторов
11. Деструкторы. Зачем они нужны?
Деструктор метод, который вызывается при удалении объекта из памяти (например, при достижении конца блока, в котором была введена переменная). Деструктор имеет имя, совпадающее с именем класса, но с префиксом ~. Деструктор не имеет параметров.
class Rational
{
...
public:
~Rational()
{
}
};
Для простых классов (как Rational) деструктор объявлять не обязательно. В более сложных классах он может, например, освобождать ранее выделенную память.
Виртуальный деструктор
Практически всегда деструктор делается виртуальным. Делается это для того, чтобы корректно (без утечек памяти) уничтожались объекты не только заданного класса, а и любого производного от него. Например: в игре уровни, звуки и спрайты могут создаваться загрузчиком, а уничтожаться — менеджером памяти, для которого нет разницы между уровнем и спрайтом.
12. Друзья
Обычное объявление компонентной функции гарантирует три логически различные вещи:
функция имеет доступ к скрытой части объявления класса;
функция находится в области видимости класса;
функция должна вызываться для объекта (имеется указатель this).
Объявив функцию как static, мы придаем ей только первые два свойства. В С++, объявив функцию как friend, мы наделяем ее только первым свойством. Таким образом, друг класса – это функция, которая не является компонентом класса, но которой разрешается использовать его защищенные и скрытые компоненты. Друга класса нельзя вызвать посредством операции доступа к компоненту класса, кроме случая, когда друг является компонентом другого класса. Пример:
class X {
int a;
friend void friend_set(X*, int);
public void member_set(int);
};
void friend_set(X* p, int i) {p->a = i;};
void X::member_set(int i) {a = i};
void f {
X obj;
friend_set(&obj, 10);
obj.member_set(10);
};
Механизм друзей важен потому, что функция может быть другом двух классов и потому – гораздо эффективнее обычной функции, оперирующей объектами обоих классов. Например, мы могли бы захотеть определить функцию, которая умножает матрицу на вектор. Естественно, что классы matrix и vector скрывают свое представление и обеспечивают полный набор операций для манипулирования объектами своих типов. Однако наша функция не может быть членом обоих классов. Если ее описать как обычную функцию с использованием компонентных функций обоих классов, мы можем получить не очень эффективный код. Выход – в объявлении этой функции другом обоих классов:
class matrix; // объявили класс матриц
class vector {
float v[4];
// . . .
friend vector multiply(const matrix&, const vector&);
};
class matrix {
vector v[4];
// . . .
friend vector multiply(const matrix&, const vector&);
};
Мы можем теперь написать функцию умножения, которая использует элементы векторов и матриц непосредственно:
vector multiply(const matrix& m, const vector& v) {
vector r;
for (int i = 0; i < 4; i++) { // r[i] = m[i] * v
r.v[i] = 0;
for (int j = 0; j < 4; j++) r.v[i] += m.v[i][j] * v.v[j];
};
return r;
}
Объявление друзей можно поместить как в открытой, так и закрытой части класса – не имеет значения, где именно. Так же, как и компонентные функции, друзья явно указываются в объявлении класса, Поэтому они являются часть интерфейса класса в той же мере, что и компонентные функции. В то же время дружественная функция вызывается как обычная функция. Она не получает указателя this и конкретный объект может передаваться ей только через механизм параметров.
Компонентная функция одного класса может быть другом другого:
class X {
// . . .
void f();
};
class Y {
// . . .
friend void X::f();
};
Если сразу все компонентные функции класса Х должны быть объявлены друзьями класса Y, то можно применить более короткую форму записи:
class Y {
// . . .
friend class X;
};
Функция, первое объявление которой содержит спецификатор friend, считается также внешней. Из сказанного следует:
static void f() { /* . . . */};
class X { friend g(); };// подразумевает и extern g()
class Y {
friend void f();// верно: f() имеет теперь внутренне связывание
};
static g() { /* . . . */};// ошибка: несовместимое связывание