6.x – Резюме к главе 6 и небольшой тест

Добавлено 22 мая 2021 в 18:58

Краткое резюме

В этой главе мы рассмотрели много материала. Хорошая работа!

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

Пользовательские пространства имен – это пространства имен, которые вы определяете для своих собственных объявлений. Пространства имен, предоставляемые C++ (например, глобальное пространство имен) или библиотеками (например, пространство имен std), не считаются пользовательскими пространствами имен.

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

Локальные переменные – это переменные, определенные внутри функции (включая параметры функции). Локальные переменные имеют область видимости блока, что означает, что они находятся в области видимости от точки определения до конца блока, в котором они определены. Локальные переменные имеют автоматическую продолжительность хранения, то есть они создаются в точке определения и уничтожаются в конце блока, в котором они определены.

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

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

Связывание идентификатора определяет, относятся ли другие объявления с таким же именем к этому же объекту или нет. Локальные переменные не имеют связывания. Идентификаторы с внутренним связыванием можно увидеть и использовать в одном файле, но они недоступны из других файлов. Идентификаторы с внешним связыванием можно увидеть и использовать как из файла, в котором они определены, так и из других файлов исходного кода (с помощью предварительного объявления).

По возможности избегайте использования неконстантных глобальных переменных. Глобальные переменные const обычно считаются приемлемыми. Если ваш компилятор поддерживает C++17, используйте встраиваемые (inline) переменные для глобальных констант.

Локальным переменным можно задать статическую продолжительность хранения с помощью ключевого слова static.

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

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

Ключевое слово auto имеет несколько применений. Во-первых, auto можно использовать для вывода типа, который будет определять тип переменной из ее инициализатора. auto также может использоваться как тип возвращаемого значения функции, чтобы компилятор определил тип возвращаемого значения функции из инструкций return, хотя для обычных функций этого следует избегать. auto используется как часть синтаксиса, завершающегося типом возвращаемого значения (trailing return syntax). И, наконец, начиная с C++20, auto предоставляет сокращенный способ для создания шаблонов функций. На данный момент вы обычно будете использовать его для определения типа.

Неявное преобразование типа выполняется всякий раз, когда ожидается один тип данных, но предоставляется другой тип данных. Если компилятор может выяснить, как выполнить преобразование между двумя типами, он это сделает. Если он не знает, как это сделать, он выдаст ошибку компиляции. Числовое продвижение (или расширяющее преобразование типа) происходит, когда значение одного базового типа данных преобразуется в значение более крупного базового типа данных из того же семейства (например, short в int). Числовое преобразование происходит, когда мы преобразуем значение из большего типа в меньший (например, int в short) или между разными семействами типов (int в double). Преобразования, которые могут вызвать потерю данных, называются сужающими преобразованиями.

Явное преобразование типа выполняется, когда программист явно запрашивает преобразование через приведение типов. Приведение представляет собой запрос программиста на явное преобразование типа. C++ поддерживает 5 типов приведений: приведение в стиле C, статическое приведение, константное приведение, динамическое приведение и реинтерпретирующее приведение. Как правило, вам следует избегать приведений в стиле C, константных и реинтерпретирующих приведений. static_cast используется для преобразования значения одного типа в значение другого типа и на сегодняшний день является наиболее часто используемым приведением в C++.

Наконец, C++ поддерживает безымянные пространства имен, которые неявно обрабатывают всё содержимое пространства имен, как если бы оно имело внутреннее связывание. C++ также поддерживает встраиваемые (inline) пространства имен, которые предоставляют некоторые примитивные возможности управления версиями пространств имен.

Небольшой тест

Вопрос 1

Исправьте следующую программу:

#include <iostream>
 
int main()
{
	std::cout << "Enter a positive number: ";
	int num{};
	std::cin >> num;
 
 
	if (num < 0)
		std::cout << "Negative number entered.  Making positive.\n";
		num = -num;
 
	std::cout << "You entered: " << num;
 
	return 0;
}

#include <iostream>
 
int main()
{
	std::cout << "Enter a positive number: ";
	int num{};
	std::cin >> num;
 
 
	if (num < 0)
	{ // здесь необходим блок, чтобы, если num < 0, выполнялись обе инструкции
		std::cout << "Negative number entered.  Making positive.\n";
		num = -num;
	}
 
	std::cout << "You entered: " << num;
 
	return 0;
}

Вопрос 2

Напишите файл с именем constants.h, который поможет запуститься следующей программе. Если ваш компилятор поддерживает C++17, используйте переменные inline constexpr. В противном случае используйте обычные переменные constexpr. Для max_class_size вы можете выбрать любое значение.

main.cpp:

#include "constants.h"
 
#include <iostream>
 
int main()
{
	std::cout << "How many students are in your class? ";
	int students{};
	std::cin >> students;
 
 
	if (students > constants::max_class_size)
		std::cout << "There are too many students in this class";
	else
		std::cout << "This class isn't too large";
 
	return 0;
}

constants.h:

#ifndef CONSTANTS_H
#define CONSTANTS_H
 
namespace constants
{
    // удалите ключевое слово inline, если C++17 не поддерживается
    inline constexpr int max_class_size{ 35 }; 
}
#endif

main.cpp:

#include "constants.h"
 
#include <iostream>
 
int main()
{
	std::cout << "How many students are in your class? ";
	int students{};
	std::cin >> students;
 
 
	if (students > constants::max_class_size)
		std::cout << "There are too many students in this class";
	else
		std::cout << "This class isn't too large";
 
	return 0;
}

Вопрос 3

Завершите следующую программу, написав функцию passOrFail(), которая должна возвращать true для первых 3 вызовов и false для последующих.

Используйте статическую локальную переменную, чтобы запомнить, сколько раз passOrFail() вызывалась ранее.

#include <iostream>
 
int main()
{
	std::cout << "User #1: " << (passOrFail() ? "Pass" : "Fail") << '\n';
	std::cout << "User #2: " << (passOrFail() ? "Pass" : "Fail") << '\n';
	std::cout << "User #3: " << (passOrFail() ? "Pass" : "Fail") << '\n';
	std::cout << "User #4: " << (passOrFail() ? "Pass" : "Fail") << '\n';
	std::cout << "User #5: " << (passOrFail() ? "Pass" : "Fail") << '\n';
 
	return 0;
}

Программа должна выдать следующий результат:

User #1: Pass
User #2: Pass
User #3: Pass
User #4: Fail
User #5: Fail

#include <iostream>
 
bool passOrFail()
{
	static int passes{ 3 };
	return (--passes >= 0);
}
 
int main()
{
	std::cout << "User #1: " << (passOrFail() ? "Pass\n" : "Fail\n");
	std::cout << "User #2: " << (passOrFail() ? "Pass\n" : "Fail\n");
	std::cout << "User #3: " << (passOrFail() ? "Pass\n" : "Fail\n");
	std::cout << "User #4: " << (passOrFail() ? "Pass\n" : "Fail\n");
	std::cout << "User #5: " << (passOrFail() ? "Pass\n" : "Fail\n");
 
	return 0;
}

Теги

C++ / CppLearnCppnamespacestatic_casttypedefusingБезымянное/анонимное пространство именВнешнее связываниеВнутреннее связываниеВстраиваемое (inline) пространство именВывод типа / Type inferenceДля начинающихНеявное преобразование типаОбласть видимостиОбучениеПриведение типовПрограммированиеПространство именПсевдоним типа / Type aliasРасширяющее преобразование типаСинтаксис, завершающийся возвращаемым типом / Trailing return syntaxСужающее преобразование типаЯвное преобразование типа

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.