Зачем нужен конструктор по умолчанию c
Перейти к содержимому

Зачем нужен конструктор по умолчанию c

  • автор:

Зачем нужен конструктор по умолчанию c

Любой переменной, участвующей в работе программы, требуется память и некоторое начальное значение. Для переменных встроенных типов размещение в памяти обеспечивается компилятором. Для локальных переменных память выделяется из стека программы и занимается для хранения значения данной переменной до тех, пока не закончится время ее жизни. Сложные типы данных также должны размещаться в памяти и уничтожаться когда их время жизни закончилось. Это осуществляется с использованием конструкторов и деструкторов.

Конструктор (constructor) — это функция-член, имя которой совпадает с именем класса, инициализирующая переменные-члены, распределяющая память для их хранения (new).

// конструктор по умолчанию Lens(); // полный конструктор Lens(double r1, double r2, double D, double d, double n); // конструктор копирования Lens(const Lens& one);

Деструктор (destructor) — это функция-член, имя которой представляет собой ~имя класса, предназначенная для уничтожения переменных (delete).

~Lens(); // деструктор 

Одной из особенностей конструктора и деструктора является то, что в отличие от всех остальных функций, у них нет возвращаемого значения.

4.3.1. Конструкторы

Конструктор по умолчанию

Конструктор, не требующий аргументов, называется конструктором по умолчанию. Конструктор по умолчанию не имеет аргументов и инициализирует все переменные члены какими-либо начальными значениями.

// описание конструктора по умолчанию Lens(); // реализация конструктора по умолчанию Lens::Lens()

При создании любого экземпляра класса вызывается конструктор. Если при описании экземпляра не указываются никакие параметры – вызывается конструктор по умолчанию:

// вызов конструктора по умолчанию Lens test_lens1; Lens test_lens2(); Lens test_lens3[10][10];
Полный конструктор

Полный конструктор позволяет явно инициализировать все переменные-члены класса.

// описание полного конструктора Lens(double r1,double r2,double D, double d, double n); // реализация полного конструктора Lens::Lens(double r1, double r2, double D, double d, double n)

Если при описании экземпляра класса в скобках указать параметры, при создании экземпляра класса будет вызван полный конструктор и переменные-члены инициализируются указанными значениями.

// вызов полного конструктора Lens test_lens(10., -10., 2., 5., 1.5);
Неполный конструктор

Возможен и неполный конструктор, когда в списке параметров указываются не все возможные параметры для инициализации членов класса, а только наиболее часто используемые. Остальные параметры будут инициализированы значениями по умолчанию.

// описание неполного конструктора Lens(double r1, double r2); // реализация неполного конструктора Lens::Lens(double r1, double r2) < m_R1=r1; m_R2=r2; m_d=0.; m_D=0.; m_n=1.; >// вызов неполного конструктора Lens lens(10., -10.);

Инициализация переменных-членов класса в конструкторах может осуществляться не только в теле конструктора, но и после оператора :. При этом, во время присваивания переменной-члену значения, будет вызываться не оператор присваивания, а конструктор. Для встроенных типов данных, таких как double или int, это не существенно, но если членами класса являются абстрактные типы, вызов конструктора вместо оператора присваивания будет выполняться быстрее.

Lens::Lens(double r1, double r2) : m_R1(R1) , m_R2(R2)

или такой вариант:

Lens::Lens(double R1, double R2) : m_R1(R1) , m_R2(R2) , m_d(2.) , m_D(5.) , m_n(1.5)

Конструктор копирования

Конструктор копирования создает копию уже существующего экземпляра класса, копируя поэлементно переменные-члены. Конструктор копирования также используется при передаче экземпляров класса в функции по значению. Обратите внимание, что экземпляр класса передается в конструктор по константной ссылке.

// описание конструктора копирования Lens(const Lens& l); // реализация конструктора копирования Lens::Lens(const Lens& l) : m_R1(l.m_R1) , m_R2(l.m_R2) , m_d(l.m_d) , m_D(l.m_D) , m_n(l.m_n) < >// вызов конструктора копирования Lens lens1(10., -10.); Lens lens2(lens1);

4.3.2. Деструктор (пример 4.4. Конструктор и деструктор класса Матрица)

Деструктор осуществляет освобождение памяти, например уничтожение объектов размещенных динамически.

В классе Lens никакого динамического размещения не происходило, поэтому деструктор будет пустой, но его наличие все равно обязательно. Для примера реализации деструктора, представим, что имеется класс Matrix, который в конструкторе динамически создает двумерный массив размерности n x m. Тогда деструктор должен освобождать память, которую выделяет конструктор.

Конструктор вызывается в момент создания переменной, деструктор вызывается когда время жизни переменной закончилось, то есть когда встречается закрывающая фигурная скобка > блока, в которой была объявлен экземпляр класса, либо когда вызывается оператор delete при динамическом размещении экземпляра класса.

///////////////////////////////////////////////////////////////////////////// // Прикладное программирование // Пример 4.4. Класс Матрица // matrix.h // // Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// // проверка на повторное подключение файла #if !defined MATRIX_H #define MATRIX_H ///////////////////////////////////////////////////////////////////////////// // класс Матрица class Matrix < private: //число строк и число столбцов int m_rows, m_cols; //указатель на динамический массив данных double* m_data; public: //конструктор по умолчанию Matrix(); //полный конструктор Matrix(int rows, int cols); //деструктор ~Matrix(); // . >; ///////////////////////////////////////////////////////////////////////////// #endif //defined MATRIX_H 
///////////////////////////////////////////////////////////////////////////// // Прикладное программирование // Пример 4.4. Класс Матрица // matrix.cpp // // Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include using namespace std; // подключение описания класса #include "matrix.h" ///////////////////////////////////////////////////////////////////////////// // конструктор по умолчанию Matrix::Matrix() : m_rows(0) , m_cols(0) , m_data(NULL) < >///////////////////////////////////////////////////////////////////////////// // полный конструктор Matrix::Matrix(int rows, int cols) : m_rows(rows) , m_cols(cols) < m_data=new double [rows*cols]; for(int i=0; i > ///////////////////////////////////////////////////////////////////////////// //деструктор Matrix::~Matrix() < if(m_data != NULL) < delete [] m_data; > > ///////////////////////////////////////////////////////////////////////////// 
///////////////////////////////////////////////////////////////////////////// // Прикладное программирование // Пример 4.4. Класс Матрица // test_matrix.cpp // // Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// // подключение описания класса #include "matrix.h" ///////////////////////////////////////////////////////////////////////////// void main() < // в момент создания матрицы вызывается конструктор по умолчанию Matrix a; // в момент создания матрицы 3х3 вызывается полный конструктор Matrix b(3,3); // . >// время жизни переменных a и b заканчивается, вызывается деструктор /////////////////////////////////////////////////////////////////////////////

4.3.3. Проверка правильности параметров. Исключительные ситуации

Конструкторы должны проверять передаваемые им аргументы на корректность значений. Например, показатель преломления не может быть меньше 1. Что делать, если в конструктор были переданы неправильные параметры? Для этого в языке С++ существуют исключительные ситуации.

Класс exception является стандартным базовым классом C++ для всех исключений. Исключения можно сгенерировать в случае возникновения непредвиденной ошибки, например мы предполагаем что при вызове класса Lens никто не будет пытаться задать показатель преломления меньше 1, но при этом такая ситуация возможна, и это может привести к ошибке. Сгенерировать исключительную ситуацию можно при помощи оператора throw:

if(n <1) throw exception("Index of refraction should be greater than 1.");

Для обработки возникшей исключительной ситуации используются try и catch блоки.

В блок try заключается код, в котором предположительно могут возникнуть исключительные ситуации. В нашем случае это вызов конструктора. Кроме того, в этот же блок заключают операторы, которые должны быть пропущены в случае, если исключение возникает. В нашем случае вычисление и вывод на экран параксиальных характеристик не имеет смысл выполнять, если в конструкторе возникла ошибка.

// полный конструктор Lens::Lens(double r1,double r2,double D,double d,double n) : m_r1(r1) , m_r2(r2) , m_d(d) , m_D(D) , m_n(n) < if(n<1) throw exception("Index of refraction should be greater than 1."); CalculateParaxial(); > . //---------------------------------------------------------------- // в случае возникновения исключительной ситуации внутри блока try // управление переходит к блоку catch try < Lens lens7(100., -100., 50., 5., 0.); parax=lens7.GetParaxial(); parax.write(cout); >// блок catch - обработка ошибки catch(exception& error) < // вывод на экран сообщения об ошибке cout .

Если при выполнение какого-то оператора из блока try возникает исключение – управление сразу переходит к блоку catch. В блоке catch в скобках указывается тип исключения (exception это наиболее общий вид исключения, возможны и другие типы) и имя исключения. Внутри блока catch необходимо обработать ошибку. В нашем случае мы просто выводим на экран сообщение, в каких-то случаях потребуется более сложная обработка. Функция what() содержит текст, сгенерированный в момент создания исключения.

В результаты выполнения данного блока программы на экран выведется сообщение » Index of refraction should be greater than 1.».

Если никаких исключений в try-блоке не происходит, программа игнорирует его catch-обработчик.

Если исключение было сгенерировано, но перехватывание исключения в блоке try не происходило, функция, содержащая этот оператор, немедленно завершается, и программа пытается найти охватывающий try-блок в вызывающей функции. Если нигде в вызывающих функциях не найдется блок try, программа прервется с сообщением об ошибке.

Что такое Конструктор в C++?

Конструктор – это специальная функция-член класса, которая автоматически вызывается при создании объекта этого класса. Конструкторы позволяют инициализировать члены класса и выполнять другие необходимые операции при создании объекта.

Конструктор по умолчанию:

class MyClass < public: // Конструктор по умолчанию MyClass() < // Инициализация переменных, если необходимо >>;

Параметризованный конструктор:

class Rectangle < public: // Параметризованный конструктор Rectangle(int w, int h) : width(w), height(h) < // Дополнительные операции при создании объекта >private: int width; int height; >;

Почему использовать конструкторы:

  • Конструкторы обеспечивают инициализацию объектов и подготовку к их использованию.
  • Они упрощают код, делают его более читаемым и предсказуемым.

Когда использовать конструкторы:

  • При необходимости выполнения определенных действий при создании объекта.
  • Для инициализации членов класса перед использованием объекта.

Использование конструкторов в C++ является важной частью объектно-ориентированного программирования и позволяет эффективно управлять жизненным циклом объектов.

Для чего компилятор автоматически определяет конструктор по умолчанию

При написании своего класса, если я явно не определяю конструктор, то компилятор генерирует его сам. Но возникает вопрос — для чего? Я предположил, что он должен быть всегда, что бы не было никаких ошибок, но я могу сделать так: Constructor() = delete; и класс будет без конструкторов вообще, за исключением конструктора копирования и возможно других. Так для чего тогда компилятор его определяет, если можно и без него обойтись?

Отслеживать
задан 3 мая 2021 в 13:40
n 1 k z z z n 1 k z z z
1,491 5 5 серебряных знаков 22 22 бронзовых знака

Ну а как создать объект? Если нет ни одного конструктора? Как гарантировать его (объекта) корректное состояние?

3 мая 2021 в 13:43

@Harry, я могу ошибаться, но мы же можем удалить все конструкторы (поправьте меня если это не так) и все будет хорошо, разве нет?

3 мая 2021 в 13:52

рекомендую почитать «дизайн и эволюция с++» от Страуструпа. И многие подобные вопросы просто отпадут сами собой.

printКлассы

printКонструктор по умолчанию

Определение: Конструктор по умолчанию – это конструктор, который можно вызвать без аргументов. Конструктор может иметь параметры, но все они должны иметь значения по умолчанию.

имя класса();
имя класса(тип параметра1 =значение по умолчанию, тип параметра2 =значение по умолчанию, …);

Задача: Такая же, как у любого конструктора – инициализировать все поля.

Назначение: Без этого конструктора невозможно создать массив объектов.

  • Если в классе не определен ни один конструктор, компилятор создает сам конструктор по умолчанию. В этом автоматически созданном конструкторе вызываются конструкторы по умолчанию для всех базовых классов и полей.
  • Если у какого-то поля или базового класса нет конструктора по умолчанию, компилятор при попытке самостоятельно создать конструктор по умолчанию выдаст сообщение об ошибке.
class String < int len; char * str; public: String(const char *s=""); // конструктор по умолчанию . >; String::String(const char *s):len(strlen(s)),str(new char[len+1]) < strcpy(str,s); >int main() < String a; //создание строки, используя конструктор по умолчанию String b[100]; // создание массива строк String c(); // это не определение объекта, а объявление функции без параметров. >

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *