Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Итог_Пособие C++.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.03 Mб
Скачать

8.3 Улучшение процесса инициализации объектов

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

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

В следующем фрагменте кода при создании экземпляра класса Matrix3x3 используется список инициализации, значения из которого передаются в качестве параметров в конструктор.

// Пример 8.8 - универсальная инициализация структур и классов

struct Vector3 {

float x,y,z;

void print() {

std::cout << x << y << z << std::endl;

}

};

class Matrix3x3 {

Vector3 line1;

Vector3 line2;

Vector3 line3;

public:

Matrix3x3(Vector3 v1, Vector3 v2, Vector3 v3):

line1(v1), line2(v2), line3(v3) {

}

void print() {

line1.print();

line2.print();

line3.print();

}

};

Vector3 v1 = {1,2,3};

v1.print();

v1 = {11,22,33};

v1.print();

Matrix3x3 m = {{1,2,3},{4,5,6},{7,8,9}};

m.print();

m = {{10,20,30},{40,50,60},{70,80,90}};

m.print();

Результат работы программы следующий:

123

112233

123

456

789

102030

405060

708090

Если у класса есть конструктор с параметром типа std::initializer_list, то он будет иметь больший приоритет при использовании списка инициализации.

// Пример 8.9 - приоритет конструкторов при использовании списка

// инициализации

class Vector3 {

float x,y,z;

public:

Vector3(float v): x(v), y(v), z(v) {}

Vector3(std::initializer_list<int> il)

{

if(il.size() != 3)

x = y = z = 0;

else

{

x = *(il.begin());

y = *(il.begin() + 1);

z = *(il.begin() + 2);

}

}

void print() {

std::cout << x << y << z << std::endl;

}

};

Vector3 v1(1);

Vector3 v2{1};

v1.print();

v2.print();

Результат работы программы следующий:

111

000

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

// Пример 8.10 - создание объекта класса без указания имени типа

struct Person

{

std::string name;

std::string lastName;

int age;

void print()

{

std::cout << "Name: " << name << std::endl;

std::cout << "Last name: " << lastName << std::endl;

std::cout << "Age: " << age << std::endl;

}

};

Person getPerson()

{

return {"Ivan", "Ivanov", 25};

}

int main()

{

Person p = getPerson();

p.print();

}

Результат работы программы следующий:

Name: Ivan

Last name: Ivanov

Age: 25

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

// Пример 8.11 - значения по умолчанию для переменных членов класса

class Person

{

std::string name = "Unknown";

std::string lastName = "Unknown";

int age = 0;

public:

void print()

{

std::cout << "Name: " << name << std::endl;

std::cout << "Last name: " << lastName << std::endl;

std::cout << "Age: " << age << std::endl;

}

};

Person p;

p.print();

Результат работы программы следующий:

Name: Unknown

Last name: Unknown

Age: 0

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

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

// Пример 8.12 - делегирование при инициализации объектов

class Person

{

std::string name = "Unknown";

std::string lastName = "Unknown";

int age = 0;

public:

Person(const std::string& n, const std::string& ln, int a): name(n), lastName(ln), age(a){}

Person():Person("Empty", "Empty", 0) {}

void print()

{

std::cout << "Name: " << name << std::endl;

std::cout << "Last name: " << lastName << std::endl;

std::cout << "Age: " << age << std::endl;

}

};

Person p;

p.print();

Person p1("Ivan", "Ivanov", 25);

p1.print();

Результат работы программы следующий:

Name: Empty

Last name: Empty

Age: 0

Name: Ivan

Last name: Ivanov

Age: 25

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]