- •2. Первая нормальная форма (1nf)
- •3. Вторая нормальная форма (2nf)
- •4. Третья нормальная форма (3nf)
- •Использование спецификаторов доступа при наследовании классов.
- •Использование спецификаторов доступа при объявлении членов класса.
- •Конструкторы и деструкторы их назначение, объявление и использование при наследовании классов.
- •Виртуальные функции и абстрактные классы их определение, назначение.
- •Перегрузка операторов, для чего применяется, как осуществляется.
- •Перегрузка унарных операций
- •Перегрузка бинарных операций
- •Шаблоны классов их создание и причины использования.
- •Функции преобразования. Их создание и причины применения.
- •Текстовые и бинарные потоки их организация и отличия записи данных.
- •Передача объектов в функции. Как осуществляется, возникающие проблемы и методы их устранения.
- •Возвращение объектов из функций. Как осуществляется, возникающие проблемы и методы их устранения.
- •Перегрузка конструкторов как осуществляется и зачем применяется.
- •Библиотека стандартных шаблонов, для чего предназначена, что включает.
- •Контейнеры
- •Алгоритмы
- •Функциональные объекты
- •Итераторы
- •Дружественные функции для чего используются, как определяются.
- •Массивы объектов и их обработка.
- •Сортировка массивов (пузырьком, слиянием, подсчетом, быстрая сортировка Хоара)
- •Нахождение минимальных, максимальных элементов массива.
- •Задачи динамического программирование. Построение рекуррентных соотношений.
- •Алгоритмы нахождения палиндрома в строке.
- •Битовые операции в языках программирования.
- •Двоичный поиск.
Возвращение объектов из функций. Как осуществляется, возникающие проблемы и методы их устранения.
Функция может возвращать объект в точку вызова. В качестве примера рассмотрим программу: #include <iostream.h> class myclass { int i; public: void set_i(int n) {i=n;} int get_i() {return i;} }; myclass f(); // возвращение объекта типа myclass int main() { myclass o; о = f (); cout << о.get_i() << "\n"; return 0; } myclass f() { myclass x; x.set_i(1); return x; }
Когда функция возвращает объект, автоматически создается временный объект, содержащий возвращаемое значение. Именно этот объект фактически возвращается функцией. После того, как значение возвращено, этот объект уничтожается. Уничтожение временного объекта может вызывать неожиданные побочные эффекты в некоторых ситуациях. Например, если возвращаемый функцией объект имеет деструктор, освобождающий динамически зарезервированную память, то эта память будет освобождена даже в том случае, когда объект, получающий возвращаемое значение, будет продолжать использовать ее. Как будет продемонстрировано дальше в этой книге, имеются способы преодолеть эту проблему, для чего используется перегрузка оператора присваивания и определение конструктора копирования.
class Integer
{
private:
int value;
public:
Integer(int i): value(i)
{}
Integer& operator=(const Integer& right) {
//проверка на самоприсваивание
if (this == &right) {
return *this;
}
value = right.value;
return *this;
}
};
Перегрузка конструкторов как осуществляется и зачем применяется.
Эта программа использует библиотечную функцию clock(), возвращающую число тиков, прошедших с момента запуска программы. Поделив это значение на макрос CLK_TCK, получаем значение в секундах. Прототипы для clock() и CLK_TCK содержатся в заголовочном файле time.h. #include <iostream.h> #include <stdlib.h> #include <time.h> class timer { int seconds; public: / / секунды задаются строкой timer(char *t) { seconds = atoi(t); } // секунды задаются целым числом timer (int t) { seconds = t; } // время задается в минутах и секундах timer (int min, int sec) { seconds = min*60 + sec; } void run(); }; void timer::run() { clock_t t1, t2; t1 = t2 = clock () /CLK_TCK; while (seconds) { if (t1/CLK_TCK+1 <= (t2=clock())/CLK_TCK) { seconds--; t1 = t2; } } cout << "\a"; // звонок } int main() { timer a(10), b(20), c(1, 10); a.run (); // отсчитать 10 секунд b.run (); // отсчитать 20 секунд c.run (); // отсчитать 1 минуту, 10 секунд return 0; }
Как можно видеть, при создании объектов a, b и с внутри функции main() они получают начальное значение с использованием трех различных методов, поддерживаемых перегруженными конструкторами. Каждый из них позволяет провести инициализацию для соответствующих данных.
В приведенной выше программе не видно больших достоинств перегрузки конструкторов, потому что можно просто воспользоваться только одним из способов инициализации. Однако если создается библиотека классов, которую будет использовать кто-то кроме ее автора, то, возможно, имеет смысл снабдить ее конструкторами для всех наиболее употребительных форм инициализации, позволяя программисту выбрать наиболее подходящую форму для его конкретного приложения. В следующем разделе иллюстрируется еще одно из преимуществ, обеспечиваемое перегрузкой конструкторов.
