default (C++)
Указывает, что настраиваемый или disp-интерфейс, определенный в коклассе, представляет интерфейс программирования по умолчанию.
Синтаксис
[ default(interface1, interface2) ]
Параметры
interface1
Интерфейс по умолчанию, который будет доступен для сред сценариев, создающих объект на основе класса, определенного атрибутом default .
Если исходный интерфейс по умолчанию не указан, в качестве интерфейса по умолчанию используется первое вхождение неисходного интерфейса.
interface2
(Необязательно) Исходный интерфейс по умолчанию. Этот интерфейс также необходимо указать с помощью атрибута source .
Если исходный интерфейс по умолчанию не указан, в качестве интерфейса по умолчанию используется первый исходный интерфейс.
Замечания
Атрибут default C++ имеет те же функции, что и атрибут MIDL по умолчанию . Атрибут default также используется с атрибутом case .
Пример
Следующий код показывает, как default используется в определении сокласса для указания ICustomDispatch в качестве интерфейса программирования по умолчанию:
// cpp_attr_ref_default.cpp // compile with: /LD #include "windows.h" [module(name="MyLibrary")]; [object, uuid("9E66A290-4365-11D2-A997-00C04FA37DDB")] __interface ICustom < HRESULT Custom([in] long l, [out, retval] long *pLong); >; [dual, uuid("9E66A291-4365-11D2-A997-00C04FA37DDB")] __interface IDual < HRESULT Dual([in] long l, [out, retval] long *pLong); >; [object, uuid("9E66A293-4365-11D2-A997-00C04FA37DDB")] __interface ICustomDispatch : public IDispatch < HRESULT Dispatch([in] long l, [out, retval] long *pLong); >; [ coclass, default(ICustomDispatch), source(IDual), uuid("9E66A294-4365-11D2-A997-00C04FA37DDB") ] class CClass : public ICustom, public IDual, public ICustomDispatch < HRESULT Custom(long l, long *pLong) < return(S_OK); >HRESULT Dual(long l, long *pLong) < return(S_OK); >HRESULT Dispatch(long l, long *pLong) < return(S_OK); >>; int main() < #if 0 // Can't instantiate without implementations of IUnknown/IDispatch CClass *pClass = new CClass; long llong; pClass->custom(1, &llong); pClass->dual(1, &llong); pClass->dispinterface(1, &llong); pClass->dispatch(1, &llong); delete pClass; #endif return(0); >
Требования
| Контекст атрибута | Значение |
|---|---|
| Относится к | class , элемент struct данных |
| Повторяемый | No |
| Обязательные атрибуты | coclass (при применении к class или struct ) |
| Недопустимые атрибуты | None |
Дополнительные сведения см. в разделе Контексты атрибутов.
Что означают ключевые слова default и delete в конструкторах и методах?
Создаю собственный класс unique ptr, и при поиске информации заметил, что нужно писать некоторые методы и конструкторы вот так:
UniquePtr() = default; UniquePtr &operator=(const UniquePtr &object) = delete;
Как в данном случае работают ключевые слова default и delete?
Отслеживать
задан 24 мар 2022 в 15:24
yarik test yarik test
1 1 1 бронзовый знак
конструируется по умолчанию и лишен возможности присваивания(удаленный оператор)
24 мар 2022 в 15:47
default говорит компилятору, что Вы хотите, то бы он написал реализацию по умолчанию. Иногда это нужно явно, что бы он гарантированно добавил нужную функцию. delete говорит, что такой функции не будет/не нужно генерировать. Раньше делали приватную функцию без тела, но ошибка была в процессе линковки и это приводило к разнообразным странных ошибкам. Эта штука полезна при написании синглтонов или некопируемых объектов.
24 мар 2022 в 16:35
Я просто не понимаю, если мы не хотим использовать метод/функцию, то зачем нам ее в целом объявлять или описывать, чтобы следовать правилу пяти, что конструктор присваивания обязан быть, даже если его функционал не нужен?
24 мар 2022 в 17:08
24 мар 2022 в 23:30
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Последний ваш комментарий натолкнул меня ответить. Нет, не для того, чтобы лишь бы следовать каким то правилам, а для того, чтобы явно иметь то, что вы хотите иметь.
Бывают ситуации, когда явно нужно указать компилятору, что он должен генерировать конструктор(или другую функцию_член) по умолчанию. Вот простой пример:
class UniquePtr < int* p<>; size_t sz<>; public: UniquePtr(const int* array, const size_t size) : p(array), sz(size) <> //. >;
Мы имеем конструктор с двумя аргументами, и так как мы сами написали конструктор, компилятор самостоятельно не будет генерировать другой конструктор(не имеет право), поэтому мы не сможем создать объект типа UniquePtr без аргументов для конструирования. Но если добавить UniquePtr() = default; , то можно свободно создать UniquePtr ptr
Почему это удобнее и безопаснее, чем старый способ присвоения аргументам каким то значениям по умолчанию(иногда это невозможно(например для константных аргументов) или слишком длинно и является источником путаницы), является другой темой.
UniquePtr &operator=(const UniquePtr &object) = delete;
равносильно заключении функции в приватной зоне, но в некоторых случаях этот способ дает больше гарантии для избежании от неявных ошибок(смотри комментарий от KoVadim ) , делает интерфейс более наглядным.
SWITCH
Хотя конструкция if-else-if может выполнять многочисленные проверки, она не очень элегантна. Код очень труден для восприятия и в нем может запутаться даже автор через некоторое время. С этой целью С имеет оператор принятия решений switch, выполняющий действия, основываясь на сравнении значения со списком констант символов или целых чисел. При обнаружении совпадения выполняется оператор или операторы, ассоциированные с данным значением. Оператор switch имеет следующий вид:
switch (выражение) case константа1:
последовательность операторов
break;
case константа2:
последовательность операторов
break;
case константа3:
последовательность операторов break;
.
default:
последовательность операторов
>
Оператор default выполняется, если не найдено соответствий, default необязателен и, если его нет, то в случае отсутствия совпадений ничего не происходит. Когда обнаруживается совпадение, операторы, ассоциированные с соответствующим case, выполняются до тех пор, пока не встретится оператор break. В случае default (или последнего case, если отсутствует default), оператор switch заканчивает работу при обнаружении конца.
Следует знать о трех важных моментах оператора switch:
- switch отличается от if тем, что он может выполнять только операции проверки строгого равенства, в то время как if может вычислять логические выражения и отношения.
- Не может быть двух констант в одном операторе switch, имеющих одинаковые значения. Конечно, оператор switch, включающий в себя другой оператор switch, может содержать аналогичные константы.
- Если в операторе switch используются символьные константы, они автоматически преобразуются к целочисленным значениям.
Оператор switch часто используется для обработки команд клавиатуры типа работа с меню. Как показано ниже, функция menu() отображает меню для программы проверки орфографии и вызывает соответствующие процедуры:
void menu(void)
char ch;
printf(«1. Check Spelling\n»);
printf(«2. Correct Spelling Errors\n»);
printf(«3. Display Spelling Errors\n»);
printf(«Strike Any Other Key to Skip\n»);
printf (» Enter your choice: «);
ch = getche(); /* чтение клавиатуры */
switch(ch) case ‘1’:
check_spelling();
break;
case ‘2’:
correct_errors();
break;
case ‘3’;
display_errors();
break;
default :
printf(«No option selected»);
>
>
С технической точки зрения операторы break являются необязательными в операторе switch. Они используются для окончания работы последовательности операторов, ассоциированных с данной константой. Если оператор break отсутствует, продолжают выполняться операторы следующего раздела, пока не будет достигнут оператор break или конец оператора switch. О константах выбора можно думать как о метках. Выполнение начинается с метки, соответствующей искомому значению, и продолжается, пока не будет достигнут break или конец оператора switch. Например, функция, показанная ниже, использует данную особенность оператора case для упрощения кода обработчика ввода драйвера устройства:
void inp_handler(void)
int ch, flag;
ch = read_device(); /* чтение какого-то устройства */
flag = -1;
switch(ch) case 1: /* данные случаи имеют общую последовательность */
case 2: /* операторов */
case 3:
flag = 0;
break;
case 4:
flag = 1;
case 5:
error(flag);
break;
default:
process(ch);
>
>
Данная подпрограмма иллюстрирует две грани оператора switch. Во-первых, можно иметь пустые условия. В данном случае первые три условия приводят к выполнению одних и тех же операторов:
Во-вторых, выполнение переходит к следующему case, если отсутствует break. Если ch соответствует 4, то flag устанавливается в 1, и, поскольку отсутствует оператор break, выполнение продолжается и выполняется оператор error(flag). В данном случае flag имеет значение 1. Если ch равно 5, то вызывается error(flag), а значение flag будет равно — 1. Способность запускать несколько операторов, соответствующих нескольким условиям при отсутствии оператора break, позволяет создавать эффективный код, поскольку это избавляет от необходимости дублировать код.
Важно понять, что операторы, ассоциированные с каждой меткой, являются не блоками кода, а скорее последовательностью операторов. (Сам оператор switch определяет блок.) Понимание этого необходимо в некоторых специфических ситуациях. Например, следующий фрагмент кода содержит ошибку и не будет компилироваться, поскольку невозможно объявить переменную в последовательности операторов:
Тем не менее переменная может быть добавлена:
Имеется возможность создания блока кода как одного из операторов в последовательности и объявление в нем переменной, как показано ниже:
![]() |
ЗАМЕТКА: Все ранее обсуждаемое применимо только к С, но не к С++. В С++ можно объявлять переменную в любой точке, в том числе в последовательности операторов. |
Оператор выбора switch в C(Си)
Оператор выбора switch является очень удобной заменой множественного использования операторов if. Оператор switch сравнивает значение одной переменной с несколькими константами. Основной формат для использования оператора множественного выбора switch case показан — ниже. Значение переменной указанной в условии switch сравнивается со значениями, которые следуют за ключевым словом case . Когда значение в переменной, соответствует значению в строке с оператором case , компьютер продолжит выполнение программы с этого места.
switch ( /*variable*/ ) < case const1: /*Тут находится код, который необходимо выполнить, если переменная variable будет равна const1*/ break; case const2: /*этот код выполнится, если variable будет равна const2*/ break; /*. */ default: /*Код, который выполнится, если ниодно из константых значению не соответствует значение в переменной variable*/ break; >
Когда сравниваемое значение в переменной variable совпадет с первым значением оператора case , программа начнет выполнять код, который находится между текущим оператором case и оператором break. Оператор break используется для того, чтобы прерывать ход программы в операторе switch и передавать управление следующему оператору, после switch . Если не использовать оператор break , то, сразу после того, как выполнится один блок кода, программа переключится на выполнения следующего case , даже, если константное значение не будет равно значению в переменной variable . Поэтому, в операторе выбора switch , блоки кода после case всегда должны предваряться оператором break .
Также стоит обратить в нимание на ключевое слово default , оно не является обязательным, но в то же время оно необходимо для обработки неожидынных ситуаций. Например, когда значение переменной не совпадает ни с одним из значений case , в таком случае выполнится код, который находится в ветке default . Это может быть полезно, в случае, если мы не ожидаем, что ниодно из значений case не совпало со значением переменной в условии switch . В таком случае, мы увидем, что сработал код в ветке default .
Чтобы, все ранее сказанное понять и запомнить, давайте перейдем к рассмотрению простой программы с использованием оператора выбора switch . Хотя, возможно этот пример не самый удачный, но в нем наглядно показывается весь функционал оператора switch .
#include int main() < printf( "Что бы сегодня посмотреть?\n" ); printf( "1. Стрела(Arrow)\n" ); printf( "2. Сверхъестественное(Supernatural)\n" ); printf( "3. Ходячие мертвецы(Walking Dead)\n" ); printf( "4. Выход\n" ); printf( "Ваш выбор: " ); int input; scanf( "%d", &input ); switch ( input ) < case 1: /* обратите внимание на двоеточие, точки сзапятой тут нет */ printf("«His Death Was Just The Beginning»\n"); break; case 2: printf("«Scary Just Got Sexy»\n"); break; case 3: printf("«Fight the dead. Fear the living»\n"); break; case 4: printf( "Сегодня смотреть ничего не будем :(\n" ); break; default: printf( "Неправильный ввод.\n" ); >getchar(); return 0; >
Итак, как же работает этот код? Для начала, мы сделали небольшое меню (строки5 — 10), чтобы как-то информировать пользователя, что необходимо водить в программу. Как вы уже поняли, необходимо ввести число — 1, 2, 3 или 4. В зависимости от введенного числа, программа будет срабатывать поразному. В данном примере очень хорошо видно, что вводимое значение сохраняется в переменную input , и после этого, значение в этой переменной передается в оператор switch , строка 13.В строках 13 — 29 объявлен оператор множественного выбора switch . Какже он работает? Очень просто, по порядку программа сравнивает переменную input со значениями 1, 2, 3 и 4 . Например, если мы ввели число 3, топрограмма выполнит код, который находится в строках 21-22 , при вводе единицы, программа напечатает сообщение из строки 15.Думаю суть вы уловили. Ну, а, если мы ввели другое число, отличное от заданных, выполнится блок кода в строке 27. Смотрим результат работы программы. Я ввел значение — 3, сегодня буду смотреть — Ходячих!
CppStudio.com
Что бы сегодня посмотреть? 1. Стрела(Arrow) 2. Сверхъестественное(Supernatural) 3. Ходячие мертвецы(Walking Dead) 4. Выход Ваш выбор: 3 «Fight the dead. Fear the living»
Вы можете поместить данное меню и ввод значени пользователя в цикл, тогда сможете в цикле делать выбор столько раз, сколько сами захотите. Надеюсь, что описал весь процесс достаточно понятно, тема не сложная, но для закрепления материала, поэксперементируйте с этим кодом. Удачи!
К сожалению, для данной темы пока нет подходящих задач. Если у вас есть таковые на примете, отправте их по адресу: admin@cppstudio.com. Мы их опубликуем!
