Для чего используются конструкторы
Перейти к содержимому

Для чего используются конструкторы

  • автор:

Конструктор в программировании: что это такое и как им пользоваться

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

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

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

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

Конструктор в программировании: суть и применение

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

Как правило, каждый класс имеет свой собственный конструктор. Конструкторы могут принимать аргументы или не принимать их вовсе, в зависимости от требований программы.

Применение конструкторов в программировании:

  1. Инициализация объектов: Конструкторы используются для установки значения свойств объектов в момент их создания. Это позволяет удобно задавать начальные значения для свойств и избежать ошибок в последующем использовании объекта.
  2. Удобство работы: Конструкторы делают процесс создания объектов более простым и понятным. Они позволяют явно указать значения свойств, которые должны быть заданы при создании объекта.
  3. Безопасность и контроль: Конструкторы могут проверять передаваемые аргументы на корректность и выполнять необходимые действия для подготовки объекта к использованию. Это помогает избежать ошибок и некорректного использования объекта в дальнейшем.

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

Смотрите также: Python Pulp — библиотека для оптимизации и линейного программирования

Что такое конструктор?

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

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

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

Использование конструктора при создании объекта класса позволяет задать его начальное состояние и выполнить все необходимые действия, связанные с его инициализацией. Это делает конструкторы очень полезными инструментами при разработке программного обеспечения.

Как работает конструктор?

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

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

Конструкторы могут быть перегружены, то есть определены несколько конструкторов с разными параметрами. Это позволяет создавать объекты с различными начальными значениями.

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

  1. Создание класса Person с полями name и age .
  2. Определение конструктора Person(name, age) , который принимает параметры и инициализирует соответствующие поля.
  3. Создание объекта person1 с помощью конструктора new Person(«Иван», 25) .
  4. Доступ к полям объекта person1 и их использование.

Использование конструкторов позволяет упростить процесс создания и инициализации объектов, а также обеспечивает согласованность состояния объектов одного класса.

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

Пример 1: Конструктор класса «Автомобиль»

Предположим, что нам необходимо создать класс «Автомобиль» со следующими свойствами: марка, модель, год выпуска. Для этого можно использовать конструктор:

 class Car < constructor(brand, model, year) < this.brand = brand; this.model = model; this.year = year; >> // Создание объекта с помощью конструктора const myCar = new Car('Toyota', 'Camry', 2021); console.log(myCar.brand); // Выведет: "Toyota" console.log(myCar.model); // Выведет: "Camry" console.log(myCar.year); // Выведет: 2021 

В данном примере конструктор класса «Автомобиль» принимает три аргумента — марку, модель и год выпуска автомобиля. При создании объекта с помощью конструктора, эти значения передаются в конструктор, который инициализирует свойства объекта.

Смотрите также: Операторы вывода и ввода Python

Пример 2: Конструктор класса «Пользователь»

Рассмотрим еще один пример — создание конструктора для класса «Пользователь» с свойствами «имя» и «возраст», а также методом «приветствие»:

 class User < constructor(name, age) < this.name = name; this.age = age; >greet() < console.log(`Привет, меня зовут $и мне $ лет.`); > > // Создание объекта с помощью конструктора const user = new User('Алексей', 30); // Вызов метода "приветствие" объекта user.greet(); // Выведет: "Привет, меня зовут Алексей и мне 30 лет." 

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

Плюсы и минусы конструктора

Плюсы:

1. Простота использования: Конструкторы облегчают процесс создания объектов, так как предоставляют удобный интерфейс для их инициализации. Разработчику не нужно беспокоиться о мелких деталях инициализации объектов, так как они автоматически задаются при создании экземпляра класса.

2. Гибкость и расширяемость: Конструкторы позволяют создавать объекты с различными свойствами, что делает их гибкими и легко адаптируемыми под разные условия. Кроме того, при необходимости можно создавать дополнительные конструкторы или передавать параметры, чтобы изменять поведение объектов.

3. Удобство тестирования: Конструкторы помогают упростить тестирование программного кода, так как объекты можно создавать с заранее известными значениями свойств. Это позволяет проводить более точное и систематическое тестирование функциональности программы.

Минусы:

1. Возможность ошибок: Если конструктор не правильно задан или инициализация объекта происходит неправильно, это может привести к возникновению ошибок в программе. Некорректная работа конструктора может приводить к непредвиденным результатам и затруднять отладку и исправление ошибок.

Смотрите также: Работа с PHP: полезная информация и советы

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

3. Потеря производительности: Использование конструкторов может вызывать дополнительные накладные расходы на время выполнения программы, особенно если объекты создаются с большим количеством свойств или при выполнении сложных операций и инициализации. Это может приводить к потере производительности программы и нуждаться в оптимизации кода.

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

Вопрос-ответ:

Какой смысл применения конструктора в программировании?

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

Какие параметры можно передать в конструктор?

В конструктор можно передать различные параметры в зависимости от потребностей программы. Как правило, это аргументы, значения которых используются для установки начальных значений свойств объекта. Например, в конструкторе класса «Книга» можно передать параметры «название», «автор», «год издания» и т.д.

Можно ли иметь несколько конструкторов в классе?

Да, это возможно. В классе можно определить несколько конструкторов с разным количеством и типами параметров. Это позволяет создавать объекты с различными характеристиками, используя удобные комбинации аргументов при вызове конструктора.

Какие ошибки могут возникнуть при использовании конструктора?

При использовании конструктора могут возникнуть различные ошибки. Например, если переданы некорректные аргументы или неправильно определен конструктор, может произойти ошибка компиляции или выполнения программы. Также возможны ошибки, связанные с неправильным использованием объекта после его инициализации в конструкторе.

Конструктор в программировании: что это такое и как использовать

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

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

Конструктор может принимать аргументы или не принимать их вовсе. Если конструктор не принимает аргументы, его называют безаргументным или параметризованным конструктором. Если конструктор принимает аргументы, то он называется параметризованным или аргументированным конструктором. В зависимости от сложности и функциональности объекта, конструктор может быть реализован в разных вариантах.

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

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

Конструктор в программировании: обзор и применение

Конструкторы широко используются во многих языках программирования, включая JavaScript, Python, Java и C++. В каждом из этих языков конструкторы выполняют схожую функцию – устанавливают начальные значения свойств объекта и выполняют другие необходимые действия при его создании. Однако, детали реализации конструкторов могут отличаться в разных языках.

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

1. Упрощение кода: конструкторы позволяют избежать дублирования кода и упростить инициализацию объектов.

2. Удобный интерфейс: благодаря конструкторам, создание объектов становится проще и интуитивно понятнее.

3. Гибкость: конструкторы позволяют настроить объекты согласно требованиям и изменить их свойства в процессе работы программы.

Использование конструкторов:

Для использования конструкторов необходимо в языке программирования описать класс, который будет служить шаблоном для создания объектов. Внутри этого класса определяется конструктор, который будет вызываться при создании нового объекта данного класса. Через конструктор можно установить начальные значения свойств, вызвать нужные методы и выполнить другие необходимые действия.

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

class Person < constructor(name, age) < this.name = name; this.age = age; >> const person1 = new Person('John', 30); const person2 = new Person('Jane', 25);

В данном примере класс Person имеет конструктор, который принимает два аргумента – имя и возраст. При создании нового объекта person1 и person2 задаются соответствующие значения для свойств name и age.

Смотрите также: Как установить Python на Kali Linux

Использование конструкторов позволяет создавать объекты с предопределенными свойствами и выполнять нужные действия при их создании. Это значительно упрощает процесс разработки программ и повышает гибкость кода.

Что такое конструктор в программировании?

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

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

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

Пример:

Вот пример класса «Человек», в котором определены два конструктора:

 class Человек < constructor(имя, возраст) < this.имя = имя; this.возраст = возраст; >constructor(имя, возраст, пол) < this.имя = имя; this.возраст = возраст; this.пол = пол; >> 

Первый конструктор принимает только имя и возраст, а второй конструктор дополнительно принимает пол. В результате можно создавать объекты класса «Человек» с разными наборами свойств, например:

 let человек1 = new Человек("Александр", 25); let человек2 = new Человек("Екатерина", 30, "женский"); 

Таким образом, конструкторы позволяют более гибко создавать объекты с определенными свойствами и избавляют от необходимости устанавливать все значения вручную после создания объекта.

Преимущества использования конструктора

Преимущество Описание
Удобство и гибкость Использование конструктора позволяет создавать объекты с предустановленными значениями свойств, что значительно упрощает процесс их создания и инициализации. Кроме того, конструктор позволяет легко изменять значения свойств и создавать объекты с различными значениями.
Кодоподобность Использование конструктора позволяет описывать объекты и их свойства в коде, что делает код более понятным и легко читаемым для других разработчиков. Кроме того, использование конструктора позволяет использовать передачу параметров при создании объектов, что делает создание и инициализацию объектов еще более гибкими.
Повторное использование кода Использование конструктора позволяет создавать объекты с одним и тем же набором свойств и значениями. Это позволяет повторно использовать код, что значительно упрощает разработку и поддержку программного продукта.
Контроль и безопасность Использование конструктора позволяет определить тип данных, который может быть использован при создании объекта, и установить необходимые ограничения на значения свойств. Это позволяет обеспечить контроль и безопасность при работе с объектами.

Смотрите также: Как отсортировать словарь в Python по ключам

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

Как создать конструктор в программировании?

Для создания конструктора нужно выполнить следующие шаги:

  1. Определить класс, для которого будет создаваться конструктор.
  2. Внутри класса объявить метод с именем класса. Это будет конструктор.
  3. В теле конструктора определить необходимые действия для инициализации объекта.
  4. По желанию, добавить параметры в конструктор для передачи значений при создании объекта.
  5. При создании объекта этого класса конструктор будет автоматически вызван.

Пример создания простого конструктора в языке Java:

 public class Person < private String name; private int age; // Конструктор с параметрами public Person(String name, int age) < this.name = name; this.age = age; >// Конструктор без параметров public Person() < this.name = "Unknown"; this.age = 0; >// Методы доступа к полям name и age // . > // Создание объекта с помощью конструктора с параметрами Person person1 = new Person("Иван", 30); // Создание объекта с помощью конструктора без параметров Person person2 = new Person(); 

В приведенном примере класс Person имеет два конструктора: один с параметрами name и age, другой без параметров. При создании объекта person1 конструктор с параметрами будет вызван и значения аргументов будут присвоены соответствующим полям. При создании объекта person2 будет вызван конструктор без параметров, и поля name и age будут инициализированы значениями «Unknown» и 0.

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

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

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

Java

В Java конструктор объявляется с помощью ключевого слова public и названия класса. В нем можно указать параметры, которые будут передаваться при создании объекта. Например:

public class Person < private String name; private int age; public Person(String name, int age) < this.name = name; this.age = age; >> 
Python

В Python конструктор объявляется внутри класса с помощью метода __init__ . Первым аргументом обычно указывается self , который ссылается на создаваемый объект. Затем можно указать остальные аргументы. Пример:

class Person: def __init__(self, name, age): self.name = name self.age = age 
JavaScript

В JavaScript конструктор объявляется с помощью ключевого слова constructor внутри класса. Можно указать параметры, которые будут использоваться при создании нового объекта. Пример:

class Person < constructor(name, age) < this.name = name; this.age = age; >> 

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

Смотрите также: Python 64 бита

Вопрос-ответ:

Что такое конструктор в программировании?

Конструктор в программировании — это специальный метод класса, который позволяет создавать объекты этого класса.

Какие преимущества использования конструкторов в программировании?

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

Какие виды конструкторов существуют в программировании?

В программировании существуют два основных вида конструкторов: конструктор по умолчанию (default constructor) и параметризованный конструктор (parameterized constructor). Конструктор по умолчанию не принимает аргументов и инициализирует объект значениями по умолчанию. Параметризованный конструктор принимает один или несколько аргументов и инициализирует объект значениями, переданными при вызове конструктора.

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

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

Можно ли создать несколько конструкторов для одного класса?

Да, в программировании можно создавать несколько конструкторов для одного класса. Это называется перегрузкой конструкторов. При вызове конструктора можно передавать различные аргументы, в зависимости от того, какой конструктор нужно использовать.

Что такое конструктор в программировании?

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

Конструкторы (C++)

Чтобы настроить, как класс инициализирует его члены или вызывать функции при создании объекта класса, определите конструктор. Конструкторы имеют имена, совпадающие с именами классов, и не имеют возвращаемых значений. Можно определить столько перегруженных конструкторов, сколько необходимо для настройки инициализации различными способами. Как правило, конструкторы имеют открытый доступ, поэтому код за пределами определения класса или иерархии наследования может создавать объекты класса. Но вы также можете объявить конструктор как protected или private .

Конструкторы могут при необходимости принимать список инициализаторов элементов. Это более эффективный способ инициализации элементов класса, чем назначение значений в тексте конструктора. В приведенном ниже примере показан класс Box с тремя перегруженными конструкторами. Последние два используют списки инициализации членов:

class Box < public: // Default constructor Box() <>// Initialize a Box with equal dimensions (i.e. a cube) explicit Box(int i) : m_width(i), m_length(i), m_height(i) // member init list <> // Initialize a Box with custom dimensions Box(int width, int length, int height) : m_width(width), m_length(length), m_height(height) <> int Volume() < return m_width * m_length * m_height; >private: // Will have value of 0 when default constructor is called. // If we didn't zero-init here, default constructor would // leave them uninitialized with garbage values. int m_width< 0 >; int m_length< 0 >; int m_height< 0 >; >; 

При объявлении экземпляра класса компилятор выбирает конструктор для вызова на основе правил разрешения перегрузки:

int main() < Box b; // Calls Box() // Using uniform initialization (preferred): Box b2 ; // Calls Box(int) Box b3 ; // Calls Box(int, int, int) // Using function-style notation: Box b4(2, 4, 6); // Calls Box(int, int, int) > 
  • Конструкторы могут быть объявлены как inline , friendexplicit или constexpr .
  • Конструктор может инициализировать объект, объявленный как const или volatileconst volatile . Объект становится const после завершения конструктора.
  • Чтобы определить конструктор в файле реализации, присвойте ему полное имя, как и любая другая функция-член: Box::Box()

Списки инициализатора элементов

Конструктор может иметь список инициализаторов элементов, который инициализирует элементы класса перед запуском текста конструктора. (Список инициализаторов элементов не совпадает со списком инициализаторов типа std::initializer_list .)

Предпочесть списки инициализаторов элементов вместо назначения значений в тексте конструктора. Список инициализаторов элементов напрямую инициализирует элементы. В следующем примере показан список инициализатора элементов, состоящий из всех identifier(argument) выражений после двоеточия:

 Box(int width, int length, int height) : m_width(width), m_length(length), m_height(height) <> 

Идентификатор должен ссылаться на член класса; он инициализирован со значением аргумента. Аргумент может быть одним из параметров конструктора, вызовом функции или одним std::initializer_list из них.

const элементы и члены ссылочного типа должны быть инициализированы в списке инициализатора элементов.

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

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

У конструкторов по умолчанию обычно нет параметров, но у них могут быть параметры со значениями по умолчанию.

class Box < public: Box() < /*perform any required default initialization steps*/>// All params have default values Box (int w = 1, int l = 1, int h = 1): m_width(w), m_height(h), m_length(l)<> . > 

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

#include using namespace std; class Box < public: int Volume() private: int m_width < 0 >; int m_height < 0 >; int m_length < 0 >; >; int main() < Box box1; // Invoke compiler-generated constructor cout 

Если вы используете неявный конструктор по умолчанию, обязательно инициализируйте члены в определении класса, как показано в предыдущем примере. Без этих инициализаторов члены не будут инициализированы, а вызов Volume() создаст мусорное значение. Как правило, рекомендуется инициализировать элементы таким образом, даже если не полагаться на неявный конструктор по умолчанию.

Можно запретить компилятору создавать неявный конструктор по умолчанию, определив его как deleted:

 // Default constructor Box() = delete; 

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

При вызове конструктора, созданного компилятором по умолчанию, и попытке использовать круглые скобки выдается предупреждение:

class myclass<>; int main() < myclass mc(); // warning C4930: prototyped function not called (was a variable definition intended?) >

Это оператор является примером проблемы "Большинство Vexing Parse". Можно интерпретировать myclass md(); как объявление функции или как вызов конструктора по умолчанию. Так как средства синтаксического анализа C++ предпочитают объявления по сравнению с другими вещами, выражение рассматривается как объявление функции. Дополнительные сведения см. в статье Википедии Наиболее неоднозначный анализ.

Если объявлены какие-либо конструкторы, отличные от по умолчанию, компилятор не предоставляет конструктор по умолчанию:

class Box < public: Box(int width, int length, int height) : m_width(width), m_length(length), m_height(height)<>private: int m_width; int m_length; int m_height; >; int main()< Box box1(1, 2, 3); Box box2< 2, 3, 4 >; Box box3; // C2512: no appropriate default constructor available > 

Если у класса нет конструктора по умолчанию, массив объектов этого класса не может быть создан только с помощью синтаксиса квадратной скобки. Например, учитывая предыдущий блок кода, массив Boxes нельзя объявить следующим образом:

Box boxes[3]; // C2512: no appropriate default constructor available 

Но для инициализации массива объектов Box можно использовать набор списков инициализаторов:

Box boxes[3]< < 1, 2, 3 >, < 4, 5, 6 >, < 7, 8, 9 >>; 

Дополнительные сведения см. в статье Инициализаторы.

Конструкторы копии

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

У конструктора копий может быть одна из следующих сигнатур:

 Box(Box& other); // Avoid if possible--allows modification of other. Box(const Box& other); Box(volatile Box& other); Box(volatile const Box& other); // Additional parameters OK if they have default values Box(Box& other, int i = 42, string label = "Box"); 

При определении конструктора копий необходимо также определить оператор присваивания копированием (=). Дополнительные сведения см. в статьях Присваивание и Конструкторы копий и операторы присваивания копированием.

Вы можете запретить копирование объекта, определив конструктор копий как удаленный:

 Box (const Box& other) = delete; 

При попытке копирования объекта возвращается ошибка C2280: предпринята попытка ссылки на удаленную функцию.

Конструкторы перемещения

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

Box(Box&& other); 

Компилятор выбирает конструктор перемещения, когда объект инициализирован другим объектом того же типа, если другой объект будет уничтожен и больше не нуждается в его ресурсах. В следующем примере показан один случай, когда конструктор перемещения выбирается с помощью разрешения перегрузки. В конструкторе, который вызывает get_Box() , возвращаемое значение будет xvalue (значение с истекающим сроком действия). Поэтому он не назначается какой-либо переменной и поэтому выходит из область. Чтобы создать основу для этого примера, пусть у объекта Box будет большой вектор строк, которые представляют его содержимое. Вместо копирования вектора и его строк конструктор перемещения "крадет" его из значения с истекающим сроком действия box, чтобы вектор теперь принадлежал новому объекту. Необходим только вызов std::move , так как классы vector и string реализуют собственные конструкторы перемещения.

#include #include #include #include using namespace std; class Box < public: Box() < std::cout Box(int width, int height, int length) : m_width(width), m_height(height), m_length(length) < std::cout Box(Box& other) : m_width(other.m_width), m_height(other.m_height), m_length(other.m_length) < std::cout Box(Box&& other) : m_width(other.m_width), m_height(other.m_height), m_length(other.m_length) < m_contents = std::move(other.m_contents); std::cout int Volume() < return m_width * m_height * m_length; >void Add_Item(string item) < m_contents.push_back(item); >void Print_Contents() < for (const auto& item : m_contents) < cout > private: int m_width< 0 >; int m_height< 0 >; int m_length< 0 >; vector m_contents; >; Box get_Box() < Box b(5, 10, 18); // "int,int,int" b.Add_Item("Toupee"); b.Add_Item("Megaphone"); b.Add_Item("Suit"); return b; >int main() < Box b; // "default" Box b1(b); // "copy" Box b2(get_Box()); // "move" cout > ch; // keep window open return 0; > 

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

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

Дополнительные сведения о написании нетривиального конструктора перемещения см. в статье Конструкторы перемещения и операторы присваивания перемещением.

Явные конструкторы по умолчанию и удаленные конструкторы

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

class Box2 < public: Box2() = delete; Box2(const Box2& other) = default; Box2& operator=(const Box2& other) = default; Box2(Box2&& other) = default; Box2& operator=(Box2&& other) = default; //. >; 

Конструкторы constexpr

Конструктор может быть объявлен как constexpr в следующих случаях:

  • он либо объявлен как стандартный, либо он удовлетворяет всем условиям для функций constexpr в целом;
  • у класса нет виртуальных базовых классов;
  • каждый из параметров является типом литерала;
  • Текст не является блоком пробной функции;
  • инициализированы все нестатические члены данных и подобъекты базового класса;
  • если класс является a) объединением с вариантами членов или б) имеет анонимные объединения, то инициализируется только одно из объединений;
  • каждый нестатический член данных типа класса, а все подобъекты базового класса имеют конструктор constexpr

Конструкторы списков инициализаторов

 Box(initializer_list list, int w = 0, int h = 0, int l = 0) : m_contents(list), m_width(w), m_height(h), m_length(l) <> 

Затем создайте объекты Box следующим образом:

 Box b< "apples", "oranges", "pears" >; // or . Box b2(initializer_list < "bread", "cheese", "wine" >, 2, 4, 6); 

Явные конструкторы

Если у класса имеется конструктор с одним параметром, или у всех параметров, кроме одного, имеются значения по умолчанию, тип параметра можно неявно преобразовать в тип класса. Например, если у класса Box имеется конструктор, подобный следующему:

Box(int size): m_width(size), m_length(size), m_height(size)<> 

Можно инициализировать Box следующим образом:

Box b = 42; 

Или передать целое значение функции, принимающей объект Box:

class ShippingOrder < public: ShippingOrder(Box b, double postage) : m_box(b), m_postage(postage)<>private: Box m_box; double m_postage; > //elsewhere. ShippingOrder so(42, 10.8); 

В некоторых случаях подобные преобразования могут быть полезны, однако чаще всего они могут привести к незаметным, но серьезным ошибкам в вашем коде. В качестве общего правила следует использовать explicit ключевое слово конструктора (и определяемых пользователем операторов), чтобы предотвратить такое неявное преобразование типов:

explicit Box(int size): m_width(size), m_length(size), m_height(size)<> 

Когда конструктор является явным, эта строка вызывает ошибку компилятора: ShippingOrder so(42, 10.8); . Дополнительные сведения см. в разделе Заданные пользователем преобразования типов (C++).

Порядок строительства

Конструктор выполняет свою работу в следующем порядке.

  1. Вызывает конструкторы базовых классов и членов в порядке объявления.
  2. Если класс является производным от виртуальных базовых классов, конструктор инициализирует указатели виртуальных базовых классов объекта.
  3. Если класс имеет или наследует виртуальные функции, конструктор инициализирует указатели виртуальных функций объекта. Указатели виртуальных функций указывают на таблицу виртуальных функций класса, чтобы обеспечить правильную привязку вызовов виртуальных функций к коду.
  4. Выполняет весь код в теле функции.

В следующем примере показан порядок, в котором конструкторы базовых классов и членов вызываются в конструкторе для производного класса. Сначала вызывается базовый конструктор. Затем члены базового класса инициализированы в порядке, в котором они отображаются в объявлении класса. Наконец, вызывается производный конструктор.

#include using namespace std; class Contained1 < public: Contained1() < cout >; class Contained2 < public: Contained2() < cout >; class Contained3 < public: Contained3() < cout >; class BaseContainer < public: BaseContainer() < cout private: Contained1 c1; Contained2 c2; >; class DerivedContainer : public BaseContainer < public: DerivedContainer() : BaseContainer() < cout private: Contained3 c3; >; int main()

Появятся следующие выходные данные.

Contained1 ctor Contained2 ctor BaseContainer ctor Contained3 ctor DerivedContainer ctor 

Конструктор производного класса всегда вызывает конструктор базового класса, чтобы перед выполнением любых дополнительных операций иметь в своем распоряжении полностью созданные базовые классы. Конструкторы базового класса вызываются в порядке наследования — например, если ClassA является производным от ClassB , который является производным от ClassC , сначала вызывается конструктор ClassC , затем конструктор ClassB и последним конструктор ClassA .

Если базовый класс не имеет конструктора по умолчанию, необходимо указать параметры конструктора базового класса в конструкторе производных классов:

class Box < public: Box(int width, int length, int height)< m_width = width; m_length = length; m_height = height; >private: int m_width; int m_length; int m_height; >; class StorageBox : public Box < public: StorageBox(int width, int length, int height, const string label&) : Box(width, length, height)< m_label = label; >private: string m_label; >; int main()

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

  1. Отменяется код в теле функции конструктора.
  2. Объекты базовых классов и объекты-члены удаляются в порядке, обратном объявлению.
  3. Если конструктор не делегируется, все полностью созданные объекты базового класса и члены уничтожаются. Однако, поскольку сам объект не полностью построен, деструктор не выполняется.

Производные конструкторы и расширенная инициализация агрегатов

Если конструктор базового класса не является открытым, но доступен для производного класса, то вы не можете использовать пустые фигурные скобки для инициализации объекта производного типа в /std:c++17 режиме, а затем в Visual Studio 2017 и более поздних версий.

В следующем примере показана соответствующая реакция на событие в C++14:

struct Derived; struct Base < friend struct Derived; private: Base() <>>; struct Derived : Base <>; Derived d1; // OK. No aggregate init involved. Derived d2 <>; // OK in C++14: Calls Derived::Derived() // which can call Base ctor. 

В C++17 Derived теперь считается агрегатным типом. Это означает, что инициализация Base через закрытый конструктор по умолчанию происходит непосредственно как часть расширенного правила агрегатной инициализации. Ранее частный Base конструктор был вызван с помощью Derived конструктора, и он успешно выполнен из-за friend объявления.

В следующем примере показано поведение C++17 в Visual Studio 2017 и более поздних версиях в режиме /std:c++17 :

struct Derived; struct Base < friend struct Derived; private: Base() <>>; struct Derived : Base < Derived() <>// add user-defined constructor // to call with <> initialization >; Derived d1; // OK. No aggregate init involved. Derived d2 <>; // error C2248: 'Base::Base': can't access // private member declared in class 'Base' 

Конструкторы классов с множественным наследованием

Если класс является производным от нескольких базовых классов, конструкторы базового класса вызываются в порядке, в котором они перечислены в объявлении производного класса:

#include using namespace std; class BaseClass1 < public: BaseClass1() < cout >; class BaseClass2 < public: BaseClass2() < cout >; class BaseClass3 < public: BaseClass3() < cout >; class DerivedClass : public BaseClass1, public BaseClass2, public BaseClass3 < public: DerivedClass() < cout >; int main()

Должны выводиться следующие выходные данные:

BaseClass1 ctor BaseClass2 ctor BaseClass3 ctor DerivedClass ctor 

Делегирующие конструкторы

Делегирующий конструктор вызывает другой конструктор в том же классе для выполнения некоторых операций инициализации. Эта функция полезна при наличии нескольких конструкторов, которые должны выполнять аналогичную работу. Можно написать основную логику в одном конструкторе и вызвать ее из других. В следующем упрощенном примере Box(int) делегирует свою работу Box(int,int,int):

class Box < public: // Default constructor Box() <>// Initialize a Box with equal dimensions (i.e. a cube) Box(int i) : Box(i, i, i) // delegating constructor <> // Initialize a Box with custom dimensions Box(int width, int length, int height) : m_width(width), m_length(length), m_height(height) <> //. rest of class as before >; 

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

Наследование конструкторов (C++11)

Производный класс может наследовать конструкторы из прямого базового класса с помощью using объявления, как показано в следующем примере:

#include using namespace std; class Base < public: Base() < cout Base(const Base& other) < cout explicit Base(int i) : num(i) < cout explicit Base(char c) : letter(c) < cout private: int num; char letter; >; class Derived : Base < public: // Inherit all constructors from Base using Base::Base; private: // Can't initialize newMember from Base constructors. int newMember< 0 >; >; int main() < cout /* Output: Derived d1(5) calls: Base(int) Derived d1('c') calls: Base(char) Derived d3 = d2 calls: Base(Base&) Derived d4 calls: Base()*/ 

Visual Studio 2017 и более поздних версий: оператор using в режиме и более поздних версиях преобразуется в /std:c++17 область все конструкторы базового класса, кроме тех, которые имеют идентичную сигнатуру конструкторам в производном классе. Как правило, рекомендуется использовать наследующие конструкторы, когда производный класс не объявляет новых элементов данных или конструкторов.

Шаблон класса может наследовать все конструкторы от аргумента типа, если этот тип определяет базовый класс:

template < typename T >class Derived : T < using T::T; // declare the constructors from T // . >; 

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

Конструкторы и составные классы

Классы, содержащие члены типа класса, называются составными классами. При создании члена типа класса составного класса конструктор вызывается перед собственным конструктором класса. Если у содержащегося класса нет конструктора по умолчанию, необходимо использовать список инициализации в конструкторе составного класса. В предыдущем примере StorageBox при присвоении типу переменной-члена m_label нового класса Label необходимо вызвать конструктор базового класса и инициализировать переменную m_label в конструкторе StorageBox :

class Label < public: Label(const string& name, const string& address) < m_name = name; m_address = address; >string m_name; string m_address; >; class StorageBox : public Box < public: StorageBox(int width, int length, int height, Label label) : Box(width, length, height), m_label(label)<>private: Label m_label; >; int main()< // passing a named Label Label label1< "some_name", "some_address" >; StorageBox sb1(1, 2, 3, label1); // passing a temporary label StorageBox sb2(3, 4, 5, Label< "another name", "another address" >); // passing a temporary label as an initializer list StorageBox sb3(1, 2, 3, ); > 

В этом разделе

  • Конструкторы копий и операторы присваивания копированием
  • Конструкторы перемещения и операторы присваивания перемещением
  • Делегирующие конструкторы

Для чего используются конструкторы

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

В прошлой теме был разработан следующий класс:

#include class Person < public: std::string name; unsigned age; void print() < std::cout >; int main() < Person person; // вызов конструктора person.name = "Tom"; person.age = 22; person.print(); >

Здесь при создании объекта класса Person, который называется person

Person person;

вызывается конструктор по умолчанию . Если мы не определяем в классе явным образом конструктор, как в случае выше, то компилятор автоматически компилирует конструктор по умолчанию. Подобный конструктор не принимает никаких параметров и по сути ничего не делает.

Теперь определим свой конструктор. Например, в примере выше мы устанавливаем значения для полей класса Person. Но, допустим, мы хотим, чтобы при создании объекта эти поля уже имели некоторые значения по умолчанию. Для этой цели определим конструктор:

#include class Person < public: std::string name; unsigned age; void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; std::cout >; int main() < Person tom("Tom", 38); // создаем объект - вызываем конструктор tom.print(); >

Теперь в классе Person определен конструктор:

Person(std::string p_name, unsigned p_age)

По сути конструктор представляет функцию, которая может принимать параметры и которая должна называться по имени класса. В данном случае конструктор принимает два параметра и передает их значения полям name и age, а затем выводит сообщение о создании объекта.

Если мы определяем свой конструктор, то компилятор больше не создает конструктор по умолчанию. И при создании объекта нам надо обязательно вызвать определенный нами конструктор.

Вызов конструктора получает значения для параметров и возвращает объект класса:

Person tom("Tom", 38);

После этого вызова у объекта person для поля name будет определено значение "Tom", а для поля age - значение 38. Вполедствии мы также сможем обращаться к этим полям и переустанавливать их значения.

В качестве альтернативы для создания объекта можно использовать инициализатор в фигурных скобках:

Person tom;

Тажке можно присвоить объекту результат вызова конструктора:

Person tom = Person("Tom", 38);

По сути она будет эквивалетна предыдущей.

Консольный вывод определенной выше программы:

Person has been created Name: Tom Age: 38

Конструкторы облегчают нам создание нескольких объектов, которые должны иметь разные значения:

#include class Person < public: std::string name; unsigned age; void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; std::cout >; int main() < Person tom; Person bob; Person sam; tom.print(); bob.print(); sam.print(); >

Здесь создаем три разных объекта класса Person (условно трех разных людей), и соответственно в данном случае консольный вывод будет следующим:

Person has been created Person has been created Person has been created Name: Tom Age: 38 Name: Bob Age: 42 Name: Sam Age: 25

Определение нескольких конструкторов

Подобным образом мы можем определить несколько конструкторов и затем их использовать:

#include class Person < std::string name<>; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; >Person(std::string p_name) < name = p_name; age = 18; >Person() < name = "Undefined"; age = 18; >>; int main() < Person tom; // вызываем конструктор Person(std::string p_name, unsigned p_age) Person bob; // вызываем конструктор Person(std::string p_name) Person sam; // вызываем конструктор Person() tom.print(); bob.print(); sam.print(); >

В классе Person определено три конструктора, и в функции все эти конструкторы используются для создания объектов:

Name: Tom Age: 38 Name: Bob Age: 18 Name: Undefined Age: 18

Хотя пример выше прекрасно работает, однако мы можем заметить, что все три конструктора выполняют фактически одни и те же действия - устанавливают значения переменных name и age. И в C++ можем сократить их определения, вызова из одного конструктора другой и тем самым уменьшить объем кода:

#include class Person < std::string name<>; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; std::cout Person(std::string p_name): Person(p_name, 18) // вызов первого конструктора < std::cout Person(): Person(std::string("Undefined")) // вызов второго конструктора < std::cout >; int main() < Person sam; // вызываем конструктор Person() sam.print(); >

Запись Person(string p_name): Person(p_name, 18) представляет вызов конструктора, которому передается значение параметра p_name и число 18. То есть второй конструктор делегирует действия по инициализации переменных первому конструктору. При этом второй конструктор может дополнительно определять какие-то свои действия.

Таким образом, следующее создание объекта

Person sam;

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

Данная техника еще называется делегированием конструктора , поскольку мы делегируем инициализацию другому конструктору.

Параметры по умолчанию

Как и другие функции, конструкторы могут иметь параметры по умолчанию:

#include class Person < std::string name; unsigned age; public: // передаем значения по умолчанию Person(std::string p_name = "Undefined", unsigned p_age = 18) < name = p_name; age = p_age; >void print() < std::cout >; int main() < Person tom; Person bob; Person sam; tom.print(); // Name: Tom Age: 38 bob.print(); // Name: Bob Age: 18 sam.print(); // Name: Undefined Age: 18 >

Инициализация констант и списки инициализации

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

class Person < const std::string name; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) < name = p_name; age = p_age; >>;

Этот класс не будет компилироваться из-за отсутствия инициализации константы name. Хотя ее значение устанавливается в конструкторе, но к моменту, когда инструкции из тела конструктора начнут выполняться, константы уже должны быть инициализированы. И для этого необходимо использовать списки инициализации :

#include class Person < const std::string name; unsigned age<>; public: void print() < std::cout Person(std::string p_name, unsigned p_age) : name  < age = p_age; >>; int main() < Person tom; tom.print(); // Name: Tom Age: 38 >

Списки инициализации представляют перечисления инициализаторов для каждой из переменных и констант через двоеточие после списка параметров конструктора:

Person(std::string p_name, unsigned p_age) : name

Здесь выражение name позволяет инициализировать константу значением параметра p_name. Здесь значение помещается в фигурные скобки, но также можно использовать кргулые:

Person(std::string p_name, unsigned p_age) : name(p_name)

Списки инициализации пободным образом можно использовать и для присвоения значений переменным:

class Person < const std::string name; unsigned age; public: void print() < std::cout Person(std::string p_name, unsigned p_age) : name(p_name), age(p_age) < >>;

При использовании списков инициализации важно учитывать, что передача значений должна идти в том порядке, в котором константы и переменные определены в классе. То есть в данном случае в классе сначала определена константа name, а потом переменная age. Соответственно в таком же порядке идет передача им значений. Поэтому при добавлении дополнительных полей или изменения порядка существующих придется следить, чтобы все инициализировалось в належащем порядке.

  • Глава 1. Введение в С++
    • Язык программирования С++
    • Первая программа на Windows. Компилятор g++
    • Первая программа на Windows. Компилятор Clang
    • Первая программа на Windows. Компилятор Microsoft Visual C++
    • Первая программа на Linux. Компилятор g++
    • Первая программа на MacOS. Компилятор Clang
    • Настройка параметров компиляции
    • Локализация и кириллица в консоли
    • Структура программы
    • Переменные
    • Типы данных
    • Константы
    • Ввод и вывод в консоли
    • using. Подключение пространств имен и определение псевдонимов
    • Арифметические операции
    • Статическая типизация и преобразования типов
    • Поразрядные операции
    • Операции присваивания
    • Условные выражения
    • Конструкция if-else и тернарный оператор
    • Конструкция switch-case
    • Циклы
    • Ссылки
    • Массивы
    • Многомерные массивы
    • Массивы символов
    • Введение в строки
    • Что такое указатели
    • Операции с указателями
    • Арифметика указателей
    • Константы и указатели
    • Указатели и массивы
    • Определение и объявление функций
    • Область видимости объектов
    • Параметры функции
    • Передача аргументов по значению и по ссылке
    • Константные параметры
    • Оператор return и возвращение результата
    • Указатели в параметрах функции
    • Массивы в параметрах функции
    • Параметры функции main
    • Возвращение указателей и ссылок
    • Перегрузка функций
    • Рекурсивные функции
    • Рекурсия на примере быстрой сортировки
    • Указатели на функции
    • Указатели на функции как параметры
    • Тип функции
    • Указатель на функцию как возвращаемое значение
    • Разделение программы на файлы
    • Внешние объекты
    • Динамические объекты
    • Динамические массивы
    • unique_ptr
    • shared_ptr
    • Определение классов
    • Конструкторы и инициализация объектов
    • Управление доступом. Инкапсуляция
    • Объявление и определение функций класса
    • Конструктор копирования
    • Константные объекты и функции
    • Ключевое слово this
    • Дружественные функции и классы
    • Статические члены класса
    • Деструктор
    • Структуры
    • Перечисления
    • Наследование
    • Управление доступом в базовых и производных классах
    • Скрытие функционала базового класса
    • Множественное наследование
    • Виртуальные функции и их переопределение
    • Преобразование типов
    • Динамическое преобразование
    • Особенности динамического связывания
    • Чистые виртуальные функции и абстрактные классы
    • Перегрузка операторов
    • Операторы преобразования типов
    • Оператор индексирования
    • Переопределение оператора присваивания
    • Пространства имен
    • Вложенные классы
    • Обработка исключений
    • Вложенные try-catch
    • Создание своих типов исключений
    • Тип exception
    • Типы исключений
    • Шаблоны функций
    • Шаблон класса
    • Специализация шаблона класса
    • Наследование и шаблоны классов
    • Типы контейнеров
    • Вектор
    • Итераторы
    • Операции с векторами
    • Array
    • List
    • Forward_list
    • Deque
    • Стек std::stack
    • Очередь std::queue
    • Очередь приоритетов std::priority_queue
    • Множества
    • Словарь std::map
    • Span
    • Определение строк
    • Строки с поддержкой Unicode
    • Преобразование типов и строки
    • Сравнение строк
    • Получение подстроки и проверка начала и конца строки
    • Поиск подстроки
    • Изменение строки
    • Операции с символами
    • Программа подсчета слов
    • Тип std:string_view
    • rvalue
    • Конструктор перемещения
    • Оператор присваивания с перемещением
    • Роль noexcept при перемещении
    • Объекты функций
    • Лямбда-выражения
    • Захват внешних значений в лямбда-выражениях
    • Шаблон std::function<>
    • Минимальный и максимальный элементы
    • Поиск элементов
    • Копирование элементов
    • Удаление элементов и идиома Remove-Erase Idiom
    • Сортировка
    • Представления. Фильтрация
    • Проекция данных
    • Пропуск элементов. drop_view и drop_while_view
    • Извлечение диапазона элементов. take_view и take_while_view
    • Цепочки представлений
    • Оператор requires
    • Концепты
    • Выражение requires
    • Ограничения типа для auto
    • Базовые типы для работы с потоками
    • Файловые потоки. Открытие и закрытие
    • Чтение и запись текстовых файлов
    • Переопределение операторов ввода и вывода
    • Математические константы и операции
    • Форматирование строк и функция format
    • std::optional
    • Управление ресурсами. Идиома RAII
    • Идиома копирования и замены
    • Идиома Move-and-Swap
    • Первая программа в Visual Studio
    • Первая программа в Qt Creator

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

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