- •1. Основные типы данных, объявление пользовательских типов данных typedef
- •Int (целочисленный тип)
- •2. Основные директивы препроцессора. Макросы
- •3. Указатели и динамическая память
- •4. Понятие функций. Механизм вызова функций и передача параметров
- •5. Передача и возврат параметров по значению и по указателю
- •6. Ссылки и ссылочные параметры
- •7. Перегрузка функций
- •8. Использование спецификатора const с указателями.
- •9. Понятие идентификатора. Пространства имен. Ключевое слово namespace
- •10. Анонимные пространства имен. Ключевое слово using.
- •11. Понятие структур. Оператор доступа к полям структуры по указателю.
- •12 . Понятие класса и объекта.
- •13. Время жизни переменных и объектов.
- •14. Область действия класса. Управление доступом к членам класса. Отделение интерфейса от реализации
- •15 . Понятие конструктора. Использование конструктора с аргументами по умолчанию. Конструктор по умолчанию.
- •16. Понятие деструктора. Когда вызываются конструкторы и деструкторы.
- •17. Константные объекты и функции-члены.
- •18. Дружественные функции и дружественные классы.
- •19. Использование указателя this.
- •20. Использование операции new и delete.
- •21. Статические члены класса.
- •25.Функции-операции как члены класса и как дружественные функции.
- •26.Перегрузка операции присваивания. Условия вызова оператора присваивания и конструктора копирования.
- •27. Понятие наследования. Механизм ограничения доступа при наследовании.
- •28.Приведение типа указателя базового класса к указателю производного класса и наоборот.
- •29.Переопределение членов базового класса в производном классе.
- •30. Конструкторы и деструкторы в производных классах
- •32. Неявный вызов конструкторов объектов
- •33. Понятие виртуальной функции
- •34. Понятие полиморфизма (примеры)
- •35. Абстрактные и конкретные базовые классы
- •36. Статическое и динамическое связывание
- •37. Виртуальные деструкторы
- •38. Шаблоны. Шаблонная функция
- •39. Шаблоны классов. Применение. Параметры шаблона типа typename
- •40. Шаблоны классов и наследование.
- •41. Шаблоны. Инстанцирование шаблонов и спецификация шаблонов
- •42. Понятие исключения. Когда должна использоваться обработка исключений.
- •43. Генерация исключений. Повторная генерация исключений
- •44. Перехватывание исключений
- •45. Спецификация исключений. Обработка неожидаемых исключений.
- •46. «Раскручивание» стека. Иерархия исключений стандартной библиотеки
- •47. Конструкторы, деструкторы и обработка исключений. Исключения и наследование.
- •48. Обработка неуспешного выполнения new
- •49. Стандартная библиотека шаблонов (stl). Основные типы контейнеров
- •50. Стандартная библиотека шаблонов (stl). Алгоритмы, методы, итераторы
- •51. Последовательные контейнеры: vector, list, deque. Основные методы и алгоритмы
- •52. Ассоциативные контейнеры: set, multiset, map, multimap. Основные методы и алгоритмы.
- •53. Операторы приведения типов static_cast, reinterpret_cast
- •54. Информация о типе времени выполнения (rtti). Использование функции typeid(). Оператор dynamic cast
- •55. Ключевое слово ехрlicit.Ключевое слово mutable
- •56. Классы-контейнеры и классы-итераторы
- •57. Понятие ооп. Парадигмы ооп (инкапсуляция, наследование, полиморфизм)
- •58. Основные составляющие объектного подхода: абстрагирование, инкапсуляция, модульность
- •59. Природа объекта. Состояние, поведение, идентичность объекта
- •60. Отношения между объектами. Связи. Агрегация
18. Дружественные функции и дружественные классы.
Данные(внутренние переменные) объекта защищены от воздействий из вне и доступ к ним можно получить только с помощью методов(функций) объекта. Но бывают такие случаи, когда нам необходимо получить доступ к данным объекта не используя его интерфейс. Зачем это может понадобиться ? Как я уже как-то упоминал, при доступе к внутренним переменным объекта через его методы уменьшается эффективность работы за счет затрат на вызов метода. В большинстве случаев нам это не критично, но не всегда. В некоторых случаях это может играть существенную роль. Конечно, можно добавить новый метод к классу для получения прямого доступа к внутренним переменным. Однако, в большинстве случаев, интерфейс объекта (методы) спланирован для выполнения определенного круга операций, и наша функция может оказаться как бы ни к месту. А если хуже того, нам необходимо получить прямой доступ к внутренним данным двух разных объектов ? Возникает проблема. Именно для решения подобных задач и существует возможность описание функции, метода другого класса или даже класса как дружественного(friend).
Для описания дружественной тому или иному классу функции(метода или класса) необходимо в описании этого класса объявить (описать) дружественную функцию с указанием ключевого слова friend. Если функция дружественна нескольким классам, то надо добавить это описание во все классы, к внутренним данным которых производим обращение. В большинстве языков ООП не имеет различия в какой раздел описания класса(publuc, protected или private) вставлено описание дружественной функции.Но возникает такой вопрос: А как же наша хваленая защищенность данных, если можно получить доступ к данным напрямую ?Но оказывается, что с точки зрения применимости механизма инкапсуляции, защищенность данных сохраняется, поскольку полностью исключается всякая возможность доступа к данным так, чтобы объект не был осведомлен об этом.
class A // Описание класса A
{
//...
void z(); // Описание функции z класса A
};
class B // Описание класса B
{
//...
friend void A::z(); // Описание функции z класса A как дружественной
// классу B, т.е. из функции z класса A можно
// получить доступ к внутренним переменным класса B
};
class C // Описание класса C
{
//...
friend class A; // Описание класса A как дружественного классу C,
// все функции класса A будут дружественны классу C и
// из любой функции класса A можно получить доступ к
// внутренним переменным класса C
}
19. Использование указателя this.
Каждый новый объект имеет скрытый от пользователя указатель на этот объект. По-другому это можно объяснить так. Когда объявляется объект, под него выделяется память. В памяти есть специальное поле, содержащее скрытый указатель, который адресует начало выделенной под объект памяти. Получить значение указателя в компонентах-функциях объекта можно с помощью ключевого слова this.
Для любой функции, принадлежащей классу my_class, указатель this неявно объявлен так: my_class *const this;
this – это указатель на экземпляр объекта, для которого выполняется текущий метод. Чаще всего его использовать не нужно, так как к полям и методам объекта можно обращаться просто по имени. Его использование обязательно при конфликте имен.
this есть указатель на объект, метод которого вызывается (this можно использоваться только в методах). Чаще всего без него вообще можно обойтись, если только не надо передавать указатель явным образом (как входной параметр в функцию или метод).
допустим есть класс myCl
class myCl
{
public:
int a;
void func(int); //Прототип
};
далее в какой-либо функции описываем объект данного класса и вызываем функцию func():
int main()
{
int x=3;
myCl A;
A.func(x); //вызов функции func;
return 0;
}
Таким образом в функцию func() передается параметр x, а также передается указатель на A (не явно) - это и есть указатель this.
Теперь пример функции func:
void func(int x)
{
//Сейчас указатель this указывает на A
//Можно это использовать так:
this->a=x;
//Конечно, можно было бы просто написать
//a=x;
//Но в некоторых случаях использование указателя this необходимо
//например в перегрузке операции присваивания,
//для возможности многократного присваивания
};