-
항목11. 정의되지 않은 비공개 함수보다 삭제된 함수를 선호하라Effective Modern C++ 2022. 7. 25. 17:07
코드의 특정 함수를 호출하지 못하게 하는 가장 흔한 방법은 선언을 하지 않는 것이다. 하지만 C++이 자동으로 함수를 선언하는 경우가 있으며, 그런 경우 클라이언트가 그 함수들을 호출하지 못하게 하기는 쉽지 않다.
그런 함수들의 사용을 방지하기 위한 C++98의 접근방식은 private로 선언하고 정의하지 않는 것이다. 이러면 클라이언트는 이 함수을 호출할 수 없다. 이들에 접근할 수 있는 코드(멤버 함수나 클래스의 friend 함수)에서 호출한다고 해도 정의가 없어서 링크가 실패한다.
C++11에서는 같은 목적을 달성하는 더 나은 방법이 있다. 이는 바로 선언의 끝에 "= delete" 를 붙이는 것이다. = delete를 붙인 함수를 삭제된 함수라고 부른다.public: basic_ios(const basic_ios&) = delete; // 삭제된 함수삭제된 함수는 어떠한 방법(멤버 함수나 클래스의 friend 함수)으로도 접근할 수 없고, 부적절한 용례가 링크 시점에 가서야 발견되는 C++98의 방식에 비하여 적절하다. (삭제된 함수는 private이 아니라 public으로 선언하는 것이 관례)
private 방식은 멤버 함수에만 사용할 수 있지만 삭제된 함수는 어떠한 함수도 삭제할 수 있다.
암묵적 변환에 의해 아래의 코드는 논리에는 어긋나지만 무사히 컴파일된다.bool isLucky(int number); if(isLucky('a')) ... if(isLucky(true)) ... if(isLucky(3.5)) ...이는 논리적으로 어긋나는 것이라 위의 호출들이 아예 컴파일되지 않게 만드는 것이 바람직하다.
다음과 같이 삭제된 함수로 지정한 매개변수 형식들은 암묵적 변환이 되지 않아 컴파일되지 않는다.
bool isLucky(int number); bool isLucky(char) = delete; bool isLucky(bool) = delete; bool isLucky(double) = delete;삭제된 함수의 또 하나의 장점은 원치 않는 템플릿 인스턴스화를 방지하는 것이다.
포인터에는 특별한 포인터 두 가지가 있다. 하나는 void* 포인터이다. 이 포인터는 역참조나 증가, 감소가 아예 불가능하다. 또 하나는 char* 포인터로, 개별 문자를 나타내는 것이 아니라 C 스타일 문자열을 나타낸다는 점에서 특별하다.
그래서 이 두 포인터를 호출하지 못하게 하는 템플릿을 구현한다 해보자.template<> void processPointer<void>(void*) = delete; template<> void processPointer<const void>(const void*) = delete; template<> void processPointer<char>(char*) = delete;const volatile void*, const volatile char*, wchar_t, char16_t, char32_t의 포인터들에 대한 버전들도 삭제하면 좋다.
하지만 private로 템플릿의 일부 인스턴스화를 방지하는 것은 불가능하다. 그 이유는 템플릿 특수화는 반드시 클래스 범위가 아니라 이름공간 범위에서 작성해야 한다는 것이다. 그래서 다른 접근 수준을 지정할 필요가 없는 삭제된 함수는 멤버 함수를 클래스 바깥에서 삭제하는 것이 가능하다.class Widget{ public: ... template<typename T> void processPointer(T* ptr) {...} ... }; template<> void Widget::processPointer<void>(void*) = delete;'Effective Modern C++' 카테고리의 다른 글
항목13. iterator보다 const_iterator를 선호하라 (0) 2022.07.27 항목12. 재정의 함수들을 override로 선언하라 (0) 2022.07.26 항목10. 범위 있는 enum을 선호하라. (0) 2022.07.23 항목9. typedef보다 별칭 선언을 선호하라 (0) 2022.07.20 항목8. 0과 NULL보다 nullptr을 선호하라 (0) 2022.07.20