C ++ 11로 삭제 된 함수가 오버로드 해결에 참여하는 이유는 무엇입니까?
왜 C ++ 11은 " delete
d"함수가 과부하 해결에 참여하게 합니까?
이것이 왜 유용합니까? 즉, 완전히 삭제되지 않고 숨겨지는 이유는 무엇입니까?
= delete
구문 의 목적의 절반은 사람들이 특정 매개 변수를 사용하여 특정 함수를 호출하지 못하도록하는 것입니다. 이는 주로 특정 시나리오에서 암시 적 변환을 방지하기위한 것입니다. 특정 과부하를 방지하려면 과부하 해결에 참여해야합니다.
인용 한 답변은 완벽한 예입니다.
struct onlydouble {
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
경우 delete
기능을 완전히 제거, 그것은 만들 것 = delete
이것에 구문 동등한 :
struct onlydouble2 {
onlydouble2(double);
};
다음과 같이 할 수 있습니다.
onlydouble2 val(20);
이것은 합법적 인 C ++입니다. 컴파일러는 모든 생성자를 살펴 봅니다. 그들 중 누구도 정수형을 직접 취하지 않습니다. 그러나 그들 중 하나는 암시 적 변환 후에 그것을 취할 수 있습니다. 그래서 그것을 부를 것입니다.
onlydouble val(20);
이것은 합법적 인 C ++ 가 아닙니다 . 컴파일러는 delete
d 생성자를 포함하여 모든 생성자를 살펴 봅니다 . std::intmax_t
(모든 정수 리터럴과 정확히 일치 함)을 통해 정확히 일치하는 것을 볼 수 있습니다. 따라서 컴파일러는이를 선택하고 delete
d 함수를 선택했기 때문에 즉시 오류를 발행 합니다.
= delete
단순히 "존재하지 않는다"는 의미가 아니라 "나는 이것을 금지한다"는 의미입니다. 훨씬 더 강력한 진술입니다.
나는 왜 C ++ 표준이 = delete가 "이것은 존재하지 않는다"대신 "I forbid this"를 의미한다고 말하는지 물었습니다.
"존재하지 않는다"라고 말하는 데 특별한 문법이 필요하지 않기 때문입니다. 우리는 문제의 특정 "this"를 단순히 선언하지 않음으로써이를 암시 적으로 얻습니다. "I forbid this"는 특별한 문법 없이는 달성 할 수없는 구조를 나타냅니다 . 그래서 우리는 "나는 이것을 금지한다"라고 말하는 특별한 문법을 얻습니다. 다른 것은 아닙니다.
명시적인 "존재하지 않음"문법을 사용하여 얻을 수있는 유일한 기능은 나중에 누군가가 존재한다고 선언하는 것을 방지하는 것입니다. 그리고 그것은 자체 문법이 필요할만큼 유용하지 않습니다.
그렇지 않으면 복사 생성자가 존재하지 않는다고 선언 할 방법이 없으며 그것의 존재는 무의미한 모호성을 유발할 수 있습니다.
복사 생성자는 특별한 멤버 함수입니다. 모든 클래스 에는 항상 복사 생성자가 있습니다. 항상 복사 할당 연산자, 이동 생성자 등이있는 것처럼
이러한 기능이 존재합니다. 문제는 그들에게 전화하는 것이 합법적인지 여부입니다. 그것이 = delete
존재하지 않는다는 것을 의미 한다고 말하려고한다면 , 사양은 함수가 존재하지 않는다는 것이 무엇을 의미하는지 설명해야 할 것입니다. 이것은 사양이 다루는 개념이 아닙니다.
아직 선언 / 정의되지 않은 함수를 호출하려고하면 컴파일러에서 오류가 발생합니다. 그러나 "함수가 존재하지 않음"오류가 아니라 정의되지 않은 식별자 때문에 오류가 발생합니다 (컴파일러가 그렇게보고하더라도). 다양한 생성자는 모두 오버로드 확인에 의해 호출되므로 그와 관련하여 "존재"가 처리됩니다.
모든 경우에 식별자를 통해 선언 된 함수 또는 생성자 / 소멸자 (또한 식별자를 통해 선언 된 형식 식별자)가 있습니다. 연산자 오버로딩은 구문 설탕 뒤에 식별자를 숨기지 만 여전히 존재합니다.
C ++ 사양은 "존재하지 않는 함수"라는 개념을 처리 할 수 없습니다. 과부하 불일치를 처리 할 수 있습니다. 과부하 모호성을 처리 할 수 있습니다. 그러나 거기에 무엇이 없는지 알지 못합니다. 따라서 = delete
덜 유용한 "내가이 줄을 쓴 적이없는 척"보다는 훨씬 더 유용한 "실패라고 부르려는 시도"라는 용어로 정의됩니다.
그리고 다시 첫 번째 부분을 다시 읽으십시오. 당신은 그렇게 할 수 없습니다 와 "기능이 존재하지 않습니다." 이것이 그렇게 정의 된 또 다른 이유입니다. = delete
구문 의 주요 사용 사례 중 하나 는 사용자가 특정 매개 변수 유형을 사용하도록 강제하고 명시 적으로 캐스팅하는 등의 작업을 수행 할 수 있기 때문입니다. 기본적으로 암시 적 형식 변환을 방지합니다.
당신의 제안은 그렇게하지 않을 것입니다.
C ++ Working Draft 2012-11-02는이 규칙에 대한 근거를 제공하지 않습니다.
8.4.3 삭제 된 정의 [dcl.fct.def.delete]
...
3 [ 예 : 기본이 아닌 초기화 및 비정 수 초기화를
struct onlydouble {
onlydouble() = delete; // OK, but redundant
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
— end example ]
[ Example : 해당 클래스에 대해 사용자가 선언 한 연산자 new의 삭제 된 정의를 사용하여 특정 새 표현식에서 클래스 사용을 방지 할 수 있습니다.
struct sometype {
void *operator new(std::size_t) = delete;
void *operator new[](std::size_t) = delete;
};
sometype *p = new sometype; // error, deleted class operator new
sometype *q = new sometype[3]; // error, deleted class operator new[]
— end example ]
[ Example : 복사 생성자 및 복사 할당 연산자의 삭제 된 정의를 사용하고 이동 생성자와 이동 할당 연산자의 기본 정의를 제공하여 클래스를 복사 불가능, 즉 이동 전용으로 만들 수 있습니다.
struct moveonly {
moveonly() = default;
moveonly(const moveonly&) = delete;
moveonly(moveonly&&) = default;
moveonly& operator=(const moveonly&) = delete;
moveonly& operator=(moveonly&&) = default;
~moveonly() = default;
};
moveonly *p;
moveonly q(*p); // error, deleted copy constructor
— end example ]
'IT story' 카테고리의 다른 글
오디오 녹음을위한 Android AudioRecord 대 MediaRecorder (0) | 2020.09.16 |
---|---|
iOS 9.2 이하에서 Xcode 8 빌드 충돌 (0) | 2020.09.16 |
iOS 7에서 자동 푸시 알림이 작동하지 않습니다. (0) | 2020.09.16 |
GitHub / BitBucket에서 병합 커밋 지옥을 피하는 방법 (0) | 2020.09.16 |
WPF UserControl은 어떻게 WPF UserControl을 상속 할 수 있습니까? (0) | 2020.09.16 |