The error message clearly says that the default constructor has been deleted implicitly. It even says why: the class contains a non-static, const variable, which would not be initialized by the default ctor.
class X {
const int x;
};
Since X::x
is const
, it must be initialized — but a default ctor wouldn’t normally initialize it (because it’s a POD type). Therefore, to get a default ctor, you need to define one yourself (and it must initialize x
). You can get the same kind of situation with a member that’s a reference:
class X {
whatever &x;
};
It’s probably worth noting that both of these will also disable implicit creation of an assignment operator as well, for essentially the same reason. The implicit assignment operator normally does members-wise assignment, but with a const member or reference member, it can’t do that because the member can’t be assigned. To make assignment work, you need to write your own assignment operator.
This is why a const
member should typically be static — when you do an assignment, you can’t assign the const member anyway. In a typical case all your instances are going to have the same value so they might as well share access to a single variable instead of having lots of copies of a variable that will all have the same value.
It is possible, of course, to create instances with different values though — you (for example) pass a value when you create the object, so two different objects can have two different values. If, however, you try to do something like swapping them, the const member will retain its original value instead of being swapped.
e7min 0 / 0 / 0 Регистрация: 16.01.2019 Сообщений: 42 |
||||||||||||
1 |
||||||||||||
Ошибка обращения к удалённой функции?19.12.2019, 23:45. Показов 1214. Ответов 9 Метки нет (Все метки)
Всем привет, пишу класс кулькулятор с помощью стека. И выходит вот такая непонятная ошибка, пишет, что пытаюсь обратиться к удалённой функции. Скажите пожалуйста, что значит к удалённой функции? А то даже отладчик не успевает запускаться, как программа сразу завершается с ошибкой, т.е. я даже не могу посмотреть что там происходит по сути. вот файл «tstack.h»
Вот файл «tcalculator.h»
вот файл «main.cpp», где выдаёт ошибку
0 |
Неэпический 17815 / 10586 / 2044 Регистрация: 27.09.2012 Сообщений: 26,627 Записей в блоге: 1 |
|
19.12.2019, 23:47 |
2 |
В
1 |
0 / 0 / 0 Регистрация: 16.01.2019 Сообщений: 42 |
|
19.12.2019, 23:51 [ТС] |
3 |
Croessmah, Я об этом думал, но не пойму как его делать. Тут же получается, что используется уже в нём конструктор стека. А что должен делать именно конструктор по умолчанию в калькуляторе?
0 |
817 / 504 / 211 Регистрация: 19.01.2019 Сообщений: 1,196 |
|
20.12.2019, 02:30 |
4 |
Конструктора по умолчанию(без параметров) нет в классе TStack, а уже в TCalculator безуспешно пытаются создаться TStack объекты.
1 |
Неэпический 17815 / 10586 / 2044 Регистрация: 27.09.2012 Сообщений: 26,627 Записей в блоге: 1 |
|
20.12.2019, 08:10 |
5 |
так что там работает дефолтный. Нет, дефолтный там как раз удален из-за отсутствия такового в TStack.
1 |
nalbe666 817 / 504 / 211 Регистрация: 19.01.2019 Сообщений: 1,196 |
||||||||||||
20.12.2019, 09:57 |
6 |
|||||||||||
Croessmah, ну да, но причина ошибки не в том, что нету конструктора в TCalculator, такого чтобы создать объекты TStack, а в том, как эти объекты объявлены. Если сделать так:
или
или сделать, как говорит ошибка
результат будет один, всё заработает.
1 |
e7min 0 / 0 / 0 Регистрация: 16.01.2019 Сообщений: 42 |
||||
21.12.2019, 22:15 [ТС] |
7 |
|||
nalbe666, Croessmah, спасибо за подсказки. Проблему решил добавлением в конструкторе стека инициализации, вот так:
И всё заработало нормально
0 |
Неэпический 17815 / 10586 / 2044 Регистрация: 27.09.2012 Сообщений: 26,627 Записей в блоге: 1 |
|
21.12.2019, 22:36 |
8 |
но причина ошибки не в том, что нету конструктора в TCalculator Как раз в этом причина вышеуказанной ошибки:
Error C2280 ‘TCalculator<double>::TCalculator(void)’: attempting to reference a deleted function А вот то, что конструктор по-умолчанию в Добавлено через 1 минуту
TStack(int _size = 10) Теперь этот конструктор является конструктором по-умолчанию.
1 |
817 / 504 / 211 Регистрация: 19.01.2019 Сообщений: 1,196 |
|
21.12.2019, 23:00 |
9 |
Croessmah, Почему вы эту проблему разбираете с конца? Да, компилятор зачехнулся на втором классе, т.к. не может конструктором по-умолчанию построить объекты внутри этого класса. И всё, что вы написали — верно. Только может стоит посмотреть, почему вообще так получилось? Например, если в первом классе отсутствует конструктор без параметров, так может это плохая идея, пытаться создать где-то объект этого класса через отсутствующий конструктор?
1 |
Неэпический 17815 / 10586 / 2044 Регистрация: 27.09.2012 Сообщений: 26,627 Записей в блоге: 1 |
|
21.12.2019, 23:09 |
10 |
nalbe666, Вы же сами указали способы решения проблемы без исправления первого класса. Странно было бы, если бы исправив следствие решилась проблема. Проблема-то как раз в TCalculator — это он использует TStack неправильно. Решения ровно два — либо исправить TStack под TCalculator, либо правильно использовать TStack в TCalculator. Источник ошибки именно в TCalculator.
2 |
В настоящее время я пытаюсь реализовать простое btree, но, похоже, здесь возникла проблема ..
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
struct element
{
int x;
int y;
element (int x, int y)
{
this->x = x;
this->y = y;
}
};
int sum(element key)
{
return key.x + key.y;
}
struct node
{
element key;
node *child_left;
node *child_right;
};class tree{
void insert(element key);
void insert(element key, node* leaf);
node* root;
tree()
{
this->root = NULL;
}
};
void tree::insert(element key){
if(this->root != NULL){
insert(key, this->root);
}else{
this->root = new node;
this->root->key.x = key.x;
this->root->key.y = key.y;
this->root->child_left = NULL;
this->root->child_right = NULL;}
}void tree::insert(element key, node* leaf){
if(sum(key) < sum(leaf->key)){
if(leaf->child_left != NULL){
insert(key, leaf->child_left);
}else{
leaf->child_left = new node;
leaf->child_left->key.x = key.x;
leaf->child_left->key.y = key.y;
leaf->child_left->child_left = NULL;
leaf->child_left->child_right = NULL;
}
}else if(sum(key) >= sum(leaf->key)){
if(leaf->child_right != NULL){
insert(key, leaf->child_right);
}else{
leaf->child_right = new node;
leaf->child_right->key.x = key.x;
leaf->child_right->key.y = key.y;
leaf->child_right->child_left = NULL;
leaf->child_right->child_right = NULL;
}
}
}
int main()
{
std::cout << "Somet"<< std::endl;
}
https://wandbox.org/permlink/0InxxBLt59PFVppt
Что дает мне сообщение об ошибке:
Start
prog.cc: In member function 'void tree::insert(element)':
prog.cc:49:20: error: use of deleted function 'node::node()'
this->root = new node;
^~~~
prog.cc:26:8: note: 'node::node()' is implicitly deleted because the default definition would be ill-formed:
struct node
^~~~
prog.cc:26:8: error: no matching function for call to 'element::element()'
prog.cc:14:5: note: candidate: 'element::element(int, int)'
element (int x, int y)
^~~~~~~
prog.cc:14:5: note: candidate expects 2 arguments, 0 provided
prog.cc:10:8: note: candidate: 'constexpr element::element(const element&)'
struct element
^~~~~~~
prog.cc:10:8: note: candidate expects 1 argument, 0 provided
prog.cc:10:8: note: candidate: 'constexpr element::element(element&&)'
prog.cc:10:8: note: candidate expects 1 argument, 0 provided
prog.cc: In member function 'void tree::insert(element, node*)':
prog.cc:66:28: error: use of deleted function 'node::node()'
leaf->child_left = new node;
^~~~
prog.cc:76:28: error: use of deleted function 'node::node()'
leaf->child_right = new node;
^~~~
1
Finish
Я не уверен, что понимаю, почему это вызывает проблемы … Так что некоторые объяснения были бы оценены, есть ли у структур (и классов) конструктор по умолчанию? так почему он жалуется?
0
Решение
Конструктор по умолчанию node
удаляется, потому что element
не имеет (это, кстати, именно то, что пытается сообщить вам сообщение об ошибке;). Нет созданного компилятором конструктора по умолчанию для element
потому что вы предоставили свой собственный конструктор (который не является конструктором по умолчанию, т.е. вы не можете вызывать его без аргументов). Либо напишите конструктор по умолчанию для node
который передает параметры в element
конструктор:
node() : key(element(1,2)) {}
или один для element
:
element(int x=0,int y=0) : x(x),y(y) {}
В последнем случае конструктор по умолчанию для node
может и будет сгенерирован компилятором, потому что это действительно так:
node() {}
1
Другие решения
Других решений пока нет …
Проблемы
Распределенные запросы, которые используют функцию OPENQUERY для обновления, удаления или вставки данных следующим образом
exec sp_dropserver 'linked1', 'droplogins'exec sp_addlinkedserver 'linked1', 'SQL Server'exec sp_setnetname 'linked1', '<servername>'exec sp_addlinkedsrvlogin 'linked1', 'false', null, '<login name>', '<password>'SET ANSI_NULLS ONgoSET ANSI_WARNINGS ONgoselect * from openquery (linked1, 'update testlinked set ssn=ssn+1')select * from openquery (linked1, 'insert into testlinked (ssn) values (1000)')select * from openquery (linked1, 'delete from testlinked where ssn=1')
могут возникать следующие сообщения об ошибках:
Сервер: сообщение 7357, уровень 16, состояние 2, строка 1 не удалось обработать объект «Update testlinked Set SSN = SSN». Поставщик OLE DB ‘ SQLOLEDB ‘ указывает на то, что в объекте нет столбцов. Сервер: MSG 7357, уровень 16, состояние 2, строка 1 [Microsoft] [драйвер SQL Server ODBC] [SQL Server] не удалось обработать объект «Update testlinked Set SSN = SSN». Поставщик OLE DB ‘ MSDASQL ‘ указывает на то, что в объекте нет столбцов.
Реальное текстовое сообщение об ошибке может отличаться в зависимости от поставщика OLE DB и выполняемой операции (обновления, вставки или удаления), но номер ошибки всегда равен 7357. Если вы используете Microsoft SQL Server 2005, появляется следующее сообщение об ошибке:
Сервер: MSG 7357, Level 16, состояние 2, строка 1 не может обработать объект «Update testlinked Set SSN = SSN». Поставщик OLE DB «SQLOLEDB» для связанного сервера «ИмяСервера» указывает на то, что у объекта нет столбцов или у текущего пользователя нет разрешений на доступ к этому объекту.
Причина
Для применения OPENQUERY требуется возвращаемый набор результатов, но инструкции UPDATE, DELETE и INSERT, используемые с OPENQUERY , не возвращают результирующий набор.
Обходное решение
Эту проблему можно обойти следующими способами:
-
Для выполнения операций вставки, обновления и удаления используются имена из четырех частей (linked_server_name. catalog. Schema. object_name).
-
Как описано в книге SQL Server Books Online, создайте ссылку на функцию OPENQUERY как целевую таблицу инструкции INSERT, UPDATE или DELETE в соответствии с возможностями поставщика OLE DB. В следующих запросах показано правильное использование поставщика OLE DB для SQL Server:
update openquery(linked1, 'select ssn from testlinked where ssn=2')set ssn=ssn + 1insert openquery(linked1, 'select ssn from testlinked where 1=0') values (1000)delete openquery(linked1, 'select ssn from testlinked where ssn>100')
Примечание. В инструкции INSERT используется предикат WHERE 1 = 0, чтобы исключить получение данных с удаленного сервера, что может привести к снижению производительности. Кроме того, для операций обновления и удаления существуют особые требования к индексам; подробные сведения приведены в разделе «Дополнительные сведения».
Дополнительная информация
Требование уникального индекса
Поставщик OLE DB для SQL Server требует, чтобы в базовой таблице существовал уникальный индекс для операций обновления или удаления. Если в удаленной таблице нет уникального индекса, при попытке обновления или удаления происходит следующее сообщение об ошибке:
Сервер: сообщение 7320, уровень 16, состояние 2, строка 1: не удалось выполнить запрос к поставщику услуг OLE DB providers «SQLOLEDB». Поставщик не поддерживает обязательный интерфейс поиска строк. Поставщик указывает на то, что возникли конфликты с другими свойствами или требованиями. [Поставщик OLE/DB вернул сообщение об ошибке: Многошаговая операция OLE DB вызвала ошибки. Установите флажок каждый из значений состояния OLE DB, если он доступен. Работа не выполнена.
Это применимо как к OPENQUERY , так и к четырем операциям Update и Delete из четырех частей. Проблему можно устранить, добавив уникальный индекс в удаленной таблице.
Динамическое выполнение с помощью OpenQuery
Иногда желательно использовать динамический запрос для достижения того же эффекта с помощью OPENQUERY, как показано в следующем примере:
begin tranSET QUOTED_IDENTIFIER OFFSET XACT_ABORT ONdeclare @cmd varchar(2500) declare @cmd1 varchar(2500) declare @var varchar(20) set @var = 'White' declare @var1 varchar(20) set @var1 = 'White1' declare @var2 varchar(20) set @var2 = 'Johnson1'select @cmd = "Update openquery(linked1,'select au_lname, au_fname from pubs.dbo.authorswhere au_lname = ''" + @var + "''' )set au_lname = '" + @var1 + "',au_fname = '" + @var2 + "'"exec ( @cmd )commit transelect * from <servername>.pubs.dbo.authors
Нужна дополнительная помощь?
Нужны дополнительные параметры?
Изучите преимущества подписки, просмотрите учебные курсы, узнайте, как защитить свое устройство и т. д.
В сообществах можно задавать вопросы и отвечать на них, отправлять отзывы и консультироваться с экспертами разных профилей.
Я работал над некоторым кодом C ++, который написал мой друг, и при компиляции с gcc4.6 получаю следующую ошибку, которую никогда раньше не видел:
ошибка: использование удаленной функции GameFSM_<> > :: hdealt :: hdealt () ’неявно удаляется, потому что определение по умолчанию было бы неправильно сформировано: неинициализированный нестатический константный член‘ const h_t FlopPokerGameFSM_<> > :: hdealt :: h ’
Изменить: это происходит из части кода, использующей boost MSM: Boost Webpage
Edit2: в исходном коде не используется .
Вообще, что означает эта ошибка? Что мне следует искать при возникновении этого типа ошибки?
- 4 и код, который вы компилируете?
- Мне было просто интересно, что означает ошибка? Нужно ли мне публиковать код и для этого?
- 1 gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 может помочь, вы также используете ускорение?
- @Sasquiha, да, я использую Boost MSM.
- 20 Поскольку это первое совпадение Google для этого типа ошибки — здесь не тот случай, но наиболее частая причина такого рода ошибок возникает после того, как вы добавили некоторый пользовательский конструктор в класс — в результате компилятор перестает создавать значение по умолчанию. конструктор, и если экземпляр класса когда-либо создается с помощью конструктора по умолчанию, появляется эта ошибка. Просто добавьте конструктор по умолчанию явно.
В сообщении об ошибке четко указано, что конструктор по умолчанию был удален. неявно. Он даже говорит, почему: класс содержит нестатическую переменную const, которая не будет инициализирована ctor по умолчанию.
Поскольку — это , он должен быть инициализирован, но ctor по умолчанию обычно не инициализирует его (потому что это тип POD). Следовательно, чтобы получить ctor по умолчанию, вам нужно определить его самостоятельно (и он должен инициализировать ). Вы можете получить такую же ситуацию с членом, который является ссылкой:
Вероятно, стоит отметить, что оба они также отключают неявное создание оператора присваивания, по сути, по той же причине. Оператор неявного присваивания обычно выполняет присвоение по членам, но с константным или ссылочным членом он не может этого сделать, потому что член не может быть назначен. Чтобы присваивание работало, вам нужно написать собственный оператор присваивания.
Вот почему член должен обычно быть статическим — когда вы выполняете назначение, вы все равно не можете назначить член const. В типичном случае все ваши экземпляры будут иметь одно и то же значение, поэтому они могут также иметь общий доступ к одной переменной вместо того, чтобы иметь множество копий переменной, которые все будут иметь одинаковое значение.
Конечно, можно создавать экземпляры с разными значениями — вы (например) передаете значение при создании объекта, поэтому два разных объекта могут иметь два разных значения. Однако если вы попытаетесь сделать что-то вроде их замены, член const сохранит свое исходное значение вместо того, чтобы быть замененным.
- @ Джеффри Коффин: фактическое сообщение об ошибке было опубликовано как редактирование, исходное сообщение об ошибке было опубликовано только
- 1 @Als: Извините, мне, вероятно, следовало прямо сказать, что я не имел в виду это как оскорбление или что-то в этом роде, просто то, что было доступно в настоящее время, показало, что эти ответы были неправильными.
- Нет проблем, я не хотел быть непреклонным … Ваш ответ фантастический и лучше всего объясняет ситуацию. +1 от меня
- Я предполагаю, что вы могли бы помочь мне с моей проблемой здесь, пожалуйста: stackoverflow.com/questions/23349524/…
- 2 @OllieFord: Это зависит от обстоятельств. Что должно произойти, если (например) вы назначите объект с одним значением в этом поле другому, имеющему другое значение в этом поле? Если он должен быть перезаписан, он не может быть const. Если это вообще не должно быть разрешено, тогда значение действительно может быть частью типа (например, параметр шаблона, если он известен во время компиляции).
Вы используете функцию, обозначенную как .
Например:
Знак = delete — это новая функция C ++ 0x. Это означает, что компилятор должен немедленно прекратить компиляцию и пожаловаться на то, что «эта функция удалена», как только пользователь использует такую функцию.
Если вы видите эту ошибку, вам следует проверить объявление функции для .
Чтобы узнать больше об этой новой функции, представленной в C ++ 0x, посмотрите это.
- 7. Из любопытства, когда подобное может быть полезно?
- @Peter: для предотвращения неявных преобразований.
- 7 На самом деле это говорит «неявно удалено, потому что …», приведенный выше пример будет явным.
- @Peter R: похоже, это пример: en.wikipedia.org/wiki/…
- 1 @Downvoter: фактическое сообщение об ошибке было опубликовано как редактирование, исходное сообщение об ошибке было опубликовано только
gcc 4.6 поддерживает новую функцию удаленных функций, где вы можете написать
чтобы отключить конструктор по умолчанию.
Здесь компилятор, очевидно, увидел, что конструктор по умолчанию не может быть сгенерирован, и сделал его за вас.
Я столкнулся с этой ошибкой при наследовании от абстрактного класса и не реализации всех чистых виртуальных методов в моем подклассе.
- 1 Точно так же я получил то же самое, унаследовав от базового класса 2-го уровня, где базовый класс 1-го уровня имел явно удаленный конструктор по умолчанию. Удаление устранило проблему без необходимости реализации всех методов.
В текущем стандарте C ++ 0x вы можете явно отключить конструкторы по умолчанию с помощью синтаксиса удаления, например.
Gcc 4.6 — первая версия, поддерживающая этот синтаксис, так что, возможно, проблема в этом …
- Думаю, это объясняет, почему я никогда не видел его раньше, поскольку недавно начал использовать gcc4.6.
- 2 Я использую этот синтаксис с GCC 4.5 в течение многих лет. Я имею в виду дни.
- Ах, я, должно быть, думал о делегированных ctors, которые есть в GCC 4.6.
Переход с gcc 4.6 на gcc 4.8 решил эту проблему.