Ошибка компилятора C2280
Объявление: попытка ссылаться на удаленную функцию
Компилятор обнаружил попытку ссылаться на deleted
функцию. Эта ошибка может быть вызвана вызовом функции-члена, которая была явно помечена как = deleted
в исходном коде. Эта ошибка также может быть вызвана вызовом неявной специальной функции-члена структуры или класса, которая автоматически объявлена и помечена deleted
компилятором. Дополнительные сведения о том, когда компилятор автоматически создает default
или deleted
специальные функции-члены, см. в разделе "Специальные функции-члены".
Пример: явно удаленные функции
Вызов явной deleted
функции вызывает эту ошибку. Явная deleted
функция-член подразумевает, что класс или структуру намеренно предназначен для предотвращения его использования, поэтому для устранения этой проблемы следует изменить код, чтобы избежать его.
// C2280_explicit.cpp
// compile with: cl /c /W4 C2280_explicit.cpp
struct A {
A();
A(int) = delete;
};
struct B {
A a1;
A a2 = A(3); // C2280, calls deleted A::A(int)
// To fix, remove the call to A(int)
};
void f() {
B b; // calls implicit B::B(void)
}
Пример: неинициализированные элементы данных
Неинициализированный элемент данных ссылочного типа или const
член данных приводит к неявному объявлению конструктора по умолчанию компилятором deleted
. Чтобы устранить эту проблему, инициализировать элемент данных при объявлении.
// C2280_uninit.cpp
// compile with: cl /c C2280_uninit.cpp
struct A {
const int i; // uninitialized const-qualified data
// members or reference type data members cause
// the implicit default constructor to be deleted.
// To fix, initialize the value in the declaration:
// const int i = 42;
} a; // C2280
Пример: элементы ссылочных и константных данных
Элемент const
данных типа или ссылочного типа приводит компилятора к объявлению deleted
оператора назначения копирования. После инициализации эти члены не могут быть назначены, поэтому простое копирование или перемещение не может работать. Чтобы устранить эту проблему, рекомендуется изменить логику, чтобы удалить операции назначения, которые вызывают ошибку.
// C2280_ref.cpp
// compile with: cl /c C2280_ref.cpp
extern int k;
struct A {
A();
int& ri = k; // a const or reference data member causes
// implicit copy assignment operator to be deleted.
};
void f() {
A a1, a2;
// To fix, consider removing this assignment.
a2 = a1; // C2280
}
Пример: Movable удаляет неявную копию
Если класс объявляет конструктор перемещения или оператор назначения перемещения, но не объявляет явно конструктор копирования, компилятор неявно объявляет конструктор копирования и определяет его как deleted
. Аналогичным образом, если класс объявляет конструктор перемещения или оператор назначения перемещения, но не объявляет явным образом оператор назначения копирования, компилятор неявно объявляет оператор назначения копирования и определяет его как deleted
. Чтобы устранить эту проблему, необходимо явно объявить эти члены.
При появлении ошибки C2280 в связи с ней unique_ptr
почти наверняка возникает ошибка, так как вы пытаетесь вызвать конструктор копирования, который является deleted
функцией. По дизайну unique_ptr
невозможно скопировать. Вместо этого используйте конструктор перемещения для передачи владения.
// C2280_move.cpp
// compile with: cl /c C2280_move.cpp
class base
{
public:
base();
~base();
base(base&&);
// Move constructor causes copy constructor to be
// implicitly declared as deleted. To fix this
// issue, you can explicitly declare a copy constructor:
// base(base&);
// If you want the compiler default version, do this:
// base(base&) = default;
};
void copy(base *p)
{
base b{*p}; // C2280
}
Пример: варианты и переменные члены
Версии компилятора до Visual Studio 2015 с обновлением 2 не соответствуют требованиям и создают конструкторы по умолчанию и деструкторы для анонимных союзов. Теперь они неявно объявлены как deleted
. Эти версии также позволили несоответствующее неявное определение конструкторов копирования default
и перемещения, default
а также операторы назначения копирования и перемещения в классах и конструкциях, имеющих volatile
переменные-члены. Теперь компилятор считает, что они имеют нетривиальные конструкторы и операторы назначения, и не создает default
реализации. Если такой класс является членом объединения или анонимного объединения внутри класса, конструкторы копирования и перемещения, а также операторы назначения копирования и перемещения профсоюза или класса неявно определяются как deleted
. Чтобы устранить эту проблему, необходимо явно объявить необходимые специальные функции-члены.
// C2280_variant.cpp
// compile with: cl /c C2280_variant.cpp
struct A {
A() = default;
A(const A&);
};
struct B {
union {
A a;
int i;
};
// To fix this issue, declare the required
// special member functions:
// B();
// B(const B& b);
};
int main() {
B b1;
B b2(b1); // C2280
}
Пример: удаленные косвенные базовые элементы
Версии компилятора до Visual Studio 2015 с обновлением 2 не соответствуют требованиям и позволяют производному классу вызывать специальные функции-члены косвенно производных private virtual
базовых классов. Компилятор теперь выдает ошибку компилятора C2280 при выполнении такого вызова.
В этом примере класс top
косвенно является производным от частной виртуальной.base
В соответствии с кодом это делает элементы base
недоступными top
; объект типа top
не может быть создан или уничтожен по умолчанию. Чтобы устранить эту проблему в коде, зависящей от старого поведения компилятора, измените промежуточный класс на использование protected virtual
производной или измените top
класс, чтобы использовать прямую производную функцию:
// C2280_indirect.cpp
// compile with: cl /c C2280_indirect.cpp
class base
{
protected:
base();
~base();
};
class middle : private virtual base {};
// Possible fix: Replace line above with:
// class middle : protected virtual base {};
class top : public virtual middle {}; // C4594, C4624
// Another possible fix: use direct derivation:
// class top : public virtual middle, private virtual base {};
void destroy(top *p)
{
delete p; // C2280
}