Udostępnij za pośrednictwem


Błąd kompilatora C2280

"deklaracja": próba odwołania się do usuniętej funkcji

Kompilator wykrył próbę deleted odwołania do funkcji. Ten błąd może być spowodowany wywołaniem funkcji składowej, która została jawnie oznaczona jako = deleted w kodzie źródłowym. Ten błąd może być również spowodowany wywołaniem niejawnej funkcji specjalnej składowej struktury lub klasy, która jest automatycznie zadeklarowana i oznaczona przez deleted kompilator. Aby uzyskać więcej informacji o tym, kiedy kompilator automatycznie generuje default lub deleted specjalne funkcje członkowskie, zobacz Specjalne funkcje składowe.

Przykład: jawnie usunięte funkcje

Wywołanie jawnej deleted funkcji powoduje ten błąd. deleted Jawna funkcja składowa oznacza, że klasa lub struktura jest celowo zaprojektowana, aby zapobiec jego użyciu, więc aby rozwiązać ten problem, należy zmienić kod, aby go uniknąć.

// 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)
}

Przykład: niezainicjowane elementy członkowskie danych

Niezainicjowany element członkowski lub const element członkowski danych typu referencyjnego powoduje, że kompilator niejawnie zadeklarował deleted konstruktor domyślny. Aby rozwiązać ten problem, zainicjuj element członkowski danych po zadeklarowaniu.

// 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

Przykład: odwołania i składowe danych const

Element const członkowski danych typu lub odwołania powoduje, że kompilator deklaruje operator przypisania kopiowania deleted . Po zainicjowaniu tych elementów członkowskich nie można przypisać do niego, więc prosta kopia lub przenoszenie nie może działać. Aby rozwiązać ten problem, zalecamy zmianę logiki w celu usunięcia operacji przypisania, które powodują błąd.

// 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
}

Przykład: wymienne usuwanie niejawnej kopii

Jeśli klasa deklaruje konstruktor przenoszenia lub operator przypisania przenoszenia, ale nie deklaruje jawnie konstruktora kopiowania, kompilator niejawnie deklaruje konstruktor kopiujący i definiuje go jako deleted. Podobnie, jeśli klasa deklaruje konstruktor przenoszenia lub operator przypisania przenoszenia, ale nie deklaruje jawnie operatora przypisania kopiowania, kompilator niejawnie deklaruje operator przypisania kopiowania i definiuje go jako deleted. Aby rozwiązać ten problem, należy jawnie zadeklarować te elementy członkowskie.

Po wyświetleniu błędu C2280 w połączeniu z elementem unique_ptr, jest prawie na pewno, ponieważ próbujesz wywołać jego konstruktor kopiowania, który jest funkcją deleted . Zgodnie z projektem unique_ptr nie można skopiować elementu . Zamiast tego użyj konstruktora przenoszenia, aby przenieść własność.

// 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
}

Przykład: wariant i elementy nietrwałe

Wersje kompilatora przed programem Visual Studio 2015 Update 2 były niezgodne i wygenerowały konstruktory domyślne i destruktory dla anonimowych związków. Są one teraz niejawnie zadeklarowane jako deleted. Te wersje zezwalały również na niezgodną niejawną definicję default konstruktorów kopiowania i przenoszenia oraz default operatorów przypisania kopiowania i przenoszenia w klasach i strukturach, które mają volatile zmienne składowe. Kompilator rozważa teraz, że mają nietrywialne konstruktory i operatory przypisania i nie generują default implementacji. Gdy taka klasa jest elementem członkowskim unii lub anonimowego związku wewnątrz klasy, konstruktory kopii i przenoszenia oraz operatory przypisania kopiowania i przenoszenia unii lub klasy są niejawnie zdefiniowane jako deleted. Aby rozwiązać ten problem, należy jawnie zadeklarować wymagane specjalne funkcje członkowskie.

// 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
}

Przykład: usunięte pośrednie składowe podstawowe

Wersje kompilatora przed programem Visual Studio 2015 Update 2 były niezgodne i zezwalały klasy pochodnej na wywoływanie specjalnych funkcji składowych pośrednio pochodnych private virtual klas bazowych. Kompilator wydaje teraz błąd kompilatora C2280, gdy takie wywołanie jest wykonywane.

W tym przykładzie klasa top pośrednio pochodzi z prywatnej wirtualnej maszyny wirtualnej base. W kodzie zgodnym sprawia to, że elementy członkowskie są base niedostępne top; obiekt typu top nie może być domyślnie skonstruowany ani zniszczony. Aby rozwiązać ten problem w kodzie, który polegał na starym zachowaniu kompilatora, zmień klasę pośrednią, aby używać protected virtual wyprowadzania, lub zmień klasę top tak, aby korzystała z wyprowadzania bezpośredniego:

// 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
}