- •Классы, Объекты и Методы
- •Struct DateStruct {
- •Int month;
- •Int year;
- •Методы классов
- •Void print () {
- •Int main () {
- •Int main () {
- •Int main () {
- •Спецификаторы доступа public и private
- •Int year; // открыто по умолчанию
- •Int main () {
- •Int main () {
- •Int main ()
- •Структуры. Классы
- •Инкапсуляция, Геттеры и Сеттеры Инкапсуляция
- •Int m_array[10];
- •Int main () {
- •IntArray array;
- •Void setValue(int index, int value) {
- •Функции доступа (геттеры и сеттеры)
- •Int m_month;
- •Int m_year;
- •Int main () {
- •Краткий обзор l-value и r-value
- •Инициализация ссылок
- •Ссылки в качестве параметров в функциях
- •Void changeN (int &ref) {
- •Int main () {
- •Int value1;
- •Int otherValue;
- •Ссылки. Указатели
- •Конструкторы
- •Int main () {
- •Конструкторы по умолчанию
- •Конструкторы с параметрами
- •Int m_numerator;
- •Int m_denominator;
- •Int getNumerator () {return m_numerator; }
- •Int getDenominator () {return m_denominator; }
- •Копирующая инициализация
- •Уменьшение количества конструкторов
- •Неявно генерируемый конструктор по умолчанию
- •Int main () {
- •Int main () {
- •Классы, содержащие другие классы
- •Int main() {
- •Список инициализации членов класса
- •Списки инициализации членов класса
- •Int m_value1;
- •Values() {
- •Int m_value1;
- •Инициализация массивов в классе
- •Инициализация переменных-членов, которые являются классами
- •Int main() {
- •Использование списков инициализации
- •Int m_value1;
- •Int m_value1;
- •Int m_value1;
- •Порядок выполнения в списке инициализации
- •Инициализация нестатических членов класса
- •Void print() {
- •Int main() {
- •Void print() {
- •Int main() {
- •Void print() {
- •Int main() {
- •Void print() {
- •Int main() {
- •Делегирующие конструкторы
- •Void DoX() {
- •Init();
- •Init();
- •Void Init()
- •Int main() {
- •Ещё о делегирующих конструкторах
- •Деструкторы
- •Имена деструкторов
- •Пример использования деструктора на практике
- •Выполнение конструкторов и деструкторов
- •Int getId() { return m_nId; }
- •Int main() {
- •Предупреждение о функции exit()
- •Скрытый указатель this
- •Скрытый указатель *this
- •Int m_number;
- •Int getNumber() { return m_number; }
- •Int main() {
- •Указатель this всегда указывает на текущий объект. Явное указание указателя this
- •Int data;
- •Цепочки методов класса
- •Заключение
Копирующая инициализация
Подобно обычным переменным, классы также можно инициализировать, используя копирующую инициализацию:
int a = 7; // копирующая инициализация
Fraction eight = Fraction (8); // копирующая инициализация,
//вызывается Fraction(8, 1)
Fraction nine = 9; // копирующая инициализация. Компилятор будет
//искать пути конвертации 9 в Fraction, что приведет к вызову
//конструктора Fraction(9, 1)
Однако рекомендуется избегать этой формы инициализации классов, так как она может быть менее эффективной.
Хотя uniform-инициализация, прямая и копирующая инициализации работают одинаково с фундаментальными типами данных, с классами это не совсем так (хотя конечный результат часто совпадает).
Правило: Не используйте копирующую инициализацию с объектами ваших классов.
Уменьшение количества конструкторов
В примере с классом Fraction и двумя конструкторами (по умолчанию и с параметрами), конструктор по умолчанию на самом деле лишний.
Мы могли бы упростить этот класс следующим образом:
#include <cassert>
class Fraction {
private:
int m_numerator;
int m_denominator;
public:
// Конструктор c умалчиваемыми значениями
Fraction (int numerator=0, int denominator=1) {
assert (denominator != 0);
m_numerator = numerator;
m_denominator = denominator;
}
int getNumerator () {return m_numerator;}
int getDenominator () {return m_denominator;}
double getValue () {return static_cast<double>(m_numerator) / m_denominator;}
};
Хотя этот конструктор по-прежнему является конструктором по умолчанию, он теперь определен таким образом, что может принимать одно или два значения, предоставленные пользователем:
Fraction drob; // вызов Fraction(0, 1)
Fraction seven(7); // вызов Fraction(7, 1)
Fraction sixTwo(6, 2); // вызов Fraction(6, 2)
На практике старайтесь сокращать количество конструкторов вашего класса.
Неявно генерируемый конструктор по умолчанию
Если ваш класс не имеет конструкторов, то язык C++ автоматически сгенерирует для вашего класса открытый конструктор по умолчанию.
Его иногда называют неявным конструктором
(или «неявно сгенерированным конструктором»).
Рассмотрим следующий класс:
class Date {
private:
int m_day = 12;
int m_month = 1;
int m_year = 2018;
};
У этого класса нет конструктора, поэтому компилятор сгенерирует следующий конструктор:
class Date {
private:
int m_day = 12;
int m_month = 1;
int m_year = 2018;
public:
Date () // неявно генерируемый конструктор
{ }
};
Этот конструктор позволяет создавать объекты класса, но не выполняет их инициализацию и не присваивает значения членам класса.
Хотя вы не можете увидеть неявно сгенерированный конструктор, но его существование можно доказать:
class Date {
private:
int m_day = 12;
int m_month = 1;
int m_year = 2018;
// Не было предоставлено конструктора, поэтому C++ автоматически //создаст открытый конструктор по умолчанию
};
