- •Методические указания к лабораторным работам
- •Лабораторная работа №1 простые программы с циклами и операторами консольного ввода/вывода
- •Задание
- •Описание примера
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №2 работа с текстовыми файлами, структурами данных и меню
- •Задание
- •Структурное программирование и функциональная декомпозиция системы
- •Функции
- •Организация меню в консольном приложении
- •Структуры данных
- •Операции с файлами
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №3 разработка и спецификация функций и модулей программы
- •Задание
- •Модульная структура программ
- •Параметры командной строки
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №4 разработка и спецификация структур данных, использование указателей и динамических массивов структур
- •Задание
- •Указатели
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №5 использование объектно-ориентированного программирования в разработке приложений
- •Задание
- •Конструкторы и деструкторы
- •Конструктор по умолчанию
- •Конструктор копирования
- •Массивы объектов
- •Friend-конструкции
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №6 использование наследования, полиморфизма и абстрактных классов
- •Задание
- •Наследование данных и методов
- •Полиморфизм и виртуальные функции
- •Абстрактный класс
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №7
- •Сложные структуры из объектов классов
- •Цель работы - изучение организации различных структур данных и разработка методов манипулирования данными.
- •Задание
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №8 разработка windows-интерфейса приложения
- •Задание
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Лабораторная работа №9 разработка и использование com-сервера
- •Задание
- •Шаблоны классов
- •Использование библиотеки atl для создания серверов сом
- •Методика выполнения
- •Содержание отчета
- •Контрольные вопросы
- •Литература
Конструктор по умолчанию
Конструктор по умолчанию не имеет аргументов и используется при создании неинициализированного объекта:
class MyClass{
public:
MyClass() { } // Конструктор по умолчанию
MyClass(int Arg) { … } // Конструктор с параметрами
….. // Остальные данные и методы
};
Без такого конструктора объекты не могли бы быть определены без задания инициализирующих значений. Если конструктор по умолчанию не объявлен явно, то компилятор автоматически назначает его. Он вызывается при таких определениях, как
MyClass clObj;
Конструктор копирования
Аргументом конструктора может быть и сам объект класса. Такой конструктор будет иметь следующий прототип:
MyClass::MyClass(MyClass &);
Такие конструкторы запускаются при копировании данных "старого" объекта во вновь создаваемый:
MyClass clObjl(7) ;
MyClass clObj2 = clObj1;
Если для класса конструктор копирования не определен, то компилятор сделает это сам.
В отличие от конструкторов, деструктор класса не имеет аргументов и не может быть перегружен. Деструкторы вызываются строго в обратной последовательности вызова соответствующих конструкторов. Они вызываются автоматически при выходе объекта из блока, в котором были определены. Единственным исключением из этого общего правила является случай, когда объект создается динамически из "кучи", путем вызова оператора new. В этом случае для корректного удаления объекта необходимо явно выполнить оператор delete, который и вызовет необходимый деструктор.
Массивы объектов
Массив объектов какого-либо класса является обычной структурой данных в ООП. Он обладает следующей особенностью: класс, массив объектов которого необходимо определить, должен иметь конструктор без параметров (конструктор по умолчанию).
class Resistors
{
double r;
void assign (double rs) { r=rs; } // Private-метод
public:
Resistors (double rs) { r=rs; } // Конструктор с параметром
Resistors() { assign(100)); } // Конструктор без параметров
double parallel (Resistors q) {
return (q.r*r/(q.r+r));
}
double series (Resistors q)
{ return (r+q.r); }
void pr () { printf ("r=%6.2f",r); }
~Resistors() { puts("Destructor invoked"); }
};
void main ()
{
Resistors rl(500), r2(1000), r3; printf("\n Class Resistors Demo\n"); printf("\n Rl: "); rl.pr(); printf("\n R2: "); r2.pr(); printf("\n R3: "); r3.pr(); printf("\n Rl + R2 =%6.2f"
"\n Rl || R2 =%6.2-f", rl.series(r2), rl.parallel(r2)); // Объявление массива объектов
Resistors many[6];
puts("\n\n Array resistors\n");
for (int i=0; i<4; i++,putch('\n'))
many[i].pr();
}
При объявлении Resistors rl(500), r2(1000); будет вызван первый конструктор с параметром. При объявлении r3, а также массива объектов класса many[6]; будет вызван второй конструктор без параметров. Определяющим фактором при этом является тип параметров. Формально это правило звучит так; объект класса с конструктором может быть членом агрегата (массива) тогда и только тогда, когда он не имеет конструктора (тогда компилятор предоставит ему конструктор по умолчанию), или если один из его конструкторов не имеет аргументов. В последнем случае именно этот конструктор будет использован при создании агрегата. Если элемент агрегата — объект класса с деструктором, то этот деструктор будет вызван при уничтожении агрегата.
Сопротивление r для всех элементов массива many[6] (объектов класса Resistors) принимает значение 100, несмотря на то что мы не пользовались оператором цикла для пробега по элементам и явного присвоения. На вопрос сколько строк вида Destructor invoked будет выведено при запуске примера, правильным будет ответ: 11 раз. Это объясняется тем, что в main объявлены девять объектов, и, кроме того, два объекта копируются (а затем уничтожаются) при входе в методы series и parallel.