컴파일러 오류 C2280

'declaration': 삭제된 함수 참조 시도

컴파일러가 함수를 참조하려는 시도를 감지했습니다 deleted . 이 오류는 소스 코드에서와 같이 명시적으로 표시된 멤버 함수에 대한 호출로 = deleted 인해 발생할 수 있습니다. 이 오류는 컴파일러에서 자동으로 선언되고 표시된 구조체 또는 클래스의 암시적 특수 멤버 함수 호출로 deleted 인해 발생할 수도 있습니다. 컴파일러가 자동으로 생성되거나 deleted 특수 멤버 함수를 default 생성하는 경우에 대한 자세한 내용은 특수 멤버 함수를 참조하세요.

예: 명시적으로 삭제된 함수

명시적으로 함수를 호출하면 이 오류가 발생합니다 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 데이터 멤버

A 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합니다. 이 문제를 해결하려면 이러한 멤버를 명시적으로 선언해야 합니다.

A와 unique_ptr관련하여 C2280 오류가 표시되면 함수인 복사 생성자를 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
}

예: Variant 및 volatile 멤버

Visual Studio 2015 업데이트 2 이전의 컴파일러 버전은 비규격이며 익명 공용 구조체에 대한 기본 생성자 및 소멸자를 생성했습니다. 이제 암시적으로 .로 deleted선언됩니다. 또한 이러한 버전에서는 멤버 변수가 있는 클래스 및 구조체 volatile 에서 복사 및 이동 생성자 및 default 복사 및 이동 할당 연산자에 대한 비규격 암시적 정의를 default 허용했습니다. 이제 컴파일러는 이러한 생성자 및 할당 연산자가 중요하지 않은 생성자 및 할당 연산자로 간주하며 구현을 생성 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
}